@polderlabs/bizar 10.4.4 → 10.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bizar-dash/dist/assets/{ActivityFeed-RQeyFifx.js → ActivityFeed-Bw4Cai7r.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityFeed-RQeyFifx.js.map → ActivityFeed-Bw4Cai7r.js.map} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-CibyssPM.js → ActivityView-BC0QQ_j9.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-CibyssPM.js.map → ActivityView-BC0QQ_j9.js.map} +1 -1
- package/bizar-dash/dist/assets/{AdminView-BjczABeB.js → AdminView-CLTNKFL4.js} +1 -1
- package/bizar-dash/dist/assets/{AdminView-BjczABeB.js.map → AdminView-CLTNKFL4.js.map} +1 -1
- package/bizar-dash/dist/assets/{AgentActivity-Bywt1twv.js → AgentActivity-DBWDByjk.js} +1 -1
- package/bizar-dash/dist/assets/{AgentActivity-Bywt1twv.js.map → AgentActivity-DBWDByjk.js.map} +1 -1
- package/bizar-dash/dist/assets/{AgentsView-BnOjjM74.js → AgentsView-DD6bCIbA.js} +1 -1
- package/bizar-dash/dist/assets/{AgentsView-BnOjjM74.js.map → AgentsView-DD6bCIbA.js.map} +1 -1
- package/bizar-dash/dist/assets/{Alert-BZGk39mB.js → Alert-pzFISNtS.js} +1 -1
- package/bizar-dash/dist/assets/{Alert-BZGk39mB.js.map → Alert-pzFISNtS.js.map} +1 -1
- package/bizar-dash/dist/assets/ArtifactsView-BVU5lfo7.js +21 -0
- package/bizar-dash/dist/assets/ArtifactsView-BVU5lfo7.js.map +1 -0
- package/bizar-dash/dist/assets/{AuthView-D4frSShw.js → AuthView-BZ-bPIOM.js} +2 -2
- package/bizar-dash/dist/assets/AuthView-BZ-bPIOM.js.map +1 -0
- package/bizar-dash/dist/assets/{Avatar-BYg0rkPA.js → Avatar-CRW81ewE.js} +1 -1
- package/bizar-dash/dist/assets/{Avatar-BYg0rkPA.js.map → Avatar-CRW81ewE.js.map} +1 -1
- package/bizar-dash/dist/assets/BackgroundJobsView-w8OZtXyI.js +1 -0
- package/bizar-dash/dist/assets/BackgroundJobsView-w8OZtXyI.js.map +1 -0
- package/bizar-dash/dist/assets/{BackupView-B875KQa4.js → BackupView-u_O3j0TG.js} +1 -1
- package/bizar-dash/dist/assets/{BackupView-B875KQa4.js.map → BackupView-u_O3j0TG.js.map} +1 -1
- package/bizar-dash/dist/assets/{Banner-C8HEcT5l.js → Banner-Du-3l05O.js} +1 -1
- package/bizar-dash/dist/assets/{Banner-C8HEcT5l.js.map → Banner-Du-3l05O.js.map} +1 -1
- package/bizar-dash/dist/assets/{Card-BtsmkhJa.js → Card-Clkvh43Q.js} +1 -1
- package/bizar-dash/dist/assets/{Card-BtsmkhJa.js.map → Card-Clkvh43Q.js.map} +1 -1
- package/bizar-dash/dist/assets/{ChatView-CkNS0SD8.js → ChatView-BTjb3mIh.js} +1 -1
- package/bizar-dash/dist/assets/{ChatView-CkNS0SD8.js.map → ChatView-BTjb3mIh.js.map} +1 -1
- package/bizar-dash/dist/assets/{Chip-XPOk0d_E.js → Chip-B7ovcm01.js} +1 -1
- package/bizar-dash/dist/assets/{Chip-XPOk0d_E.js.map → Chip-B7ovcm01.js.map} +1 -1
- package/bizar-dash/dist/assets/ClaudeSessionsView-BoZS5ldi.js +1 -0
- package/bizar-dash/dist/assets/ClaudeSessionsView-BoZS5ldi.js.map +1 -0
- package/bizar-dash/dist/assets/ClipboardView-Cb6XgYZI.js +1 -0
- package/bizar-dash/dist/assets/{ClipboardView-CPlTU5VG.js.map → ClipboardView-Cb6XgYZI.js.map} +1 -1
- package/bizar-dash/dist/assets/{ConfigView-BntUrW7s.js → ConfigView-DfTJk1uL.js} +1 -1
- package/bizar-dash/dist/assets/{ConfigView-BntUrW7s.js.map → ConfigView-DfTJk1uL.js.map} +1 -1
- package/bizar-dash/dist/assets/{DiagnosticsView-4x0Zu3yP.js → DiagnosticsView-D5Wy9xlJ.js} +1 -1
- package/bizar-dash/dist/assets/{DiagnosticsView-4x0Zu3yP.js.map → DiagnosticsView-D5Wy9xlJ.js.map} +1 -1
- package/bizar-dash/dist/assets/{DialogsView-Xd02dVAX.js → DialogsView-HVyfrXpq.js} +1 -1
- package/bizar-dash/dist/assets/{DialogsView-Xd02dVAX.js.map → DialogsView-HVyfrXpq.js.map} +1 -1
- package/bizar-dash/dist/assets/{DoctorView-DepBdQGR.js → DoctorView-Dm94WI2z.js} +2 -2
- package/bizar-dash/dist/assets/{DoctorView-DepBdQGR.js.map → DoctorView-Dm94WI2z.js.map} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-DjKtY1Qi.js → EmptyState-ccT__JZG.js} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-DjKtY1Qi.js.map → EmptyState-ccT__JZG.js.map} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsView-S4Pbm128.js → EnvVarsView-BhcIuJ6V.js} +2 -2
- package/bizar-dash/dist/assets/{EnvVarsView-S4Pbm128.js.map → EnvVarsView-BhcIuJ6V.js.map} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-CBJbEQ8B.js → ErrorState-BSqf65ka.js} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-CBJbEQ8B.js.map → ErrorState-BSqf65ka.js.map} +1 -1
- package/bizar-dash/dist/assets/{EvalView-BeAyMCD1.js → EvalView-2cbWVBUA.js} +1 -1
- package/bizar-dash/dist/assets/{EvalView-BeAyMCD1.js.map → EvalView-2cbWVBUA.js.map} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-BZr8In4c.js → GoalsView-C3QG5p7T.js} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-BZr8In4c.js.map → GoalsView-C3QG5p7T.js.map} +1 -1
- package/bizar-dash/dist/assets/{Grid--WKvqu5h.js → Grid-Bojq8Sg7.js} +1 -1
- package/bizar-dash/dist/assets/{Grid--WKvqu5h.js.map → Grid-Bojq8Sg7.js.map} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-djEbzqtk.js → HistoryView-Bum2TMMw.js} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-djEbzqtk.js.map → HistoryView-Bum2TMMw.js.map} +1 -1
- package/bizar-dash/dist/assets/{Input-h_nSOtwm.js → Input-DV-vdaV8.js} +1 -1
- package/bizar-dash/dist/assets/{Input-h_nSOtwm.js.map → Input-DV-vdaV8.js.map} +1 -1
- package/bizar-dash/dist/assets/{LibrariesView-Vez8CvNq.js → LibrariesView-DH2E2uNb.js} +1 -1
- package/bizar-dash/dist/assets/{LibrariesView-Vez8CvNq.js.map → LibrariesView-DH2E2uNb.js.map} +1 -1
- package/bizar-dash/dist/assets/LightRAGView-BFCcj7Tl.js +6 -0
- package/bizar-dash/dist/assets/LightRAGView-BFCcj7Tl.js.map +1 -0
- package/bizar-dash/dist/assets/{ListHeader-CM8QoIWG.js → ListHeader-CCD_nIHb.js} +1 -1
- package/bizar-dash/dist/assets/{ListHeader-CM8QoIWG.js.map → ListHeader-CCD_nIHb.js.map} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-DnL8E2vI.js → MemoryView-Cr-obIQY.js} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-DnL8E2vI.js.map → MemoryView-Cr-obIQY.js.map} +1 -1
- package/bizar-dash/dist/assets/{MiscView-B2YQXhZ_.js → MiscView-CDUQpYuV.js} +1 -1
- package/bizar-dash/dist/assets/{MiscView-B2YQXhZ_.js.map → MiscView-CDUQpYuV.js.map} +1 -1
- package/bizar-dash/dist/assets/{ModsView-BVM3X5xc.js → ModsView-B6OR-a4B.js} +2 -2
- package/bizar-dash/dist/assets/{ModsView-BVM3X5xc.js.map → ModsView-B6OR-a4B.js.map} +1 -1
- package/bizar-dash/dist/assets/{NotificationsView-A-Xs8BL1.js → NotificationsView-CIqtY6D0.js} +1 -1
- package/bizar-dash/dist/assets/{NotificationsView-A-Xs8BL1.js.map → NotificationsView-CIqtY6D0.js.map} +1 -1
- package/bizar-dash/dist/assets/{ObsidianView-mI3qW9OP.js → ObsidianView-Nahah8QC.js} +1 -1
- package/bizar-dash/dist/assets/{ObsidianView-mI3qW9OP.js.map → ObsidianView-Nahah8QC.js.map} +1 -1
- package/bizar-dash/dist/assets/{OverviewView-By69Cr5H.js → OverviewView-B6L_wa4M.js} +1 -1
- package/bizar-dash/dist/assets/{OverviewView-By69Cr5H.js.map → OverviewView-B6L_wa4M.js.map} +1 -1
- package/bizar-dash/dist/assets/{ProgressBar-BnaBqv-W.js → ProgressBar-KC4VXsl_.js} +1 -1
- package/bizar-dash/dist/assets/{ProgressBar-BnaBqv-W.js.map → ProgressBar-KC4VXsl_.js.map} +1 -1
- package/bizar-dash/dist/assets/{ProjectsView-C81WTFka.js → ProjectsView-DgxWiqHb.js} +1 -1
- package/bizar-dash/dist/assets/{ProjectsView-C81WTFka.js.map → ProjectsView-DgxWiqHb.js.map} +1 -1
- package/bizar-dash/dist/assets/{ProvidersView-2cn-TALE.js → ProvidersView-BOqN9omv.js} +1 -1
- package/bizar-dash/dist/assets/{ProvidersView-2cn-TALE.js.map → ProvidersView-BOqN9omv.js.map} +1 -1
- package/bizar-dash/dist/assets/SchedulesView-yMaG3Dtd.js +1 -0
- package/bizar-dash/dist/assets/SchedulesView-yMaG3Dtd.js.map +1 -0
- package/bizar-dash/dist/assets/{Select-CiGWEN8I.js → Select-Bf_P0S6H.js} +1 -1
- package/bizar-dash/dist/assets/{Select-CiGWEN8I.js.map → Select-Bf_P0S6H.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-CflGJymA.js → SettingsRow-CJb-F94Y.js} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-CflGJymA.js.map → SettingsRow-CJb-F94Y.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsView-2HSFJPPK.js → SettingsView-BvOGcgMS.js} +2 -2
- package/bizar-dash/dist/assets/SettingsView-BvOGcgMS.js.map +1 -0
- package/bizar-dash/dist/assets/{Sheet-B-CMP9-_.js → Sheet-BwMVGN-8.js} +1 -1
- package/bizar-dash/dist/assets/{Sheet-B-CMP9-_.js.map → Sheet-BwMVGN-8.js.map} +1 -1
- package/bizar-dash/dist/assets/{Slider-Z4TP_CXY.js → Slider-AjjzqI-5.js} +1 -1
- package/bizar-dash/dist/assets/{Slider-Z4TP_CXY.js.map → Slider-AjjzqI-5.js.map} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-cvkv2HbU.js → Sparkline-Z4y0YUZS.js} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-cvkv2HbU.js.map → Sparkline-Z4y0YUZS.js.map} +1 -1
- package/bizar-dash/dist/assets/{Switch-jcYo4lmp.js → Switch-B79a2t-G.js} +1 -1
- package/bizar-dash/dist/assets/{Switch-jcYo4lmp.js.map → Switch-B79a2t-G.js.map} +1 -1
- package/bizar-dash/dist/assets/{TasksView-CQaSFzWY.js → TasksView-G-s_pwwr.js} +1 -1
- package/bizar-dash/dist/assets/{TasksView-CQaSFzWY.js.map → TasksView-G-s_pwwr.js.map} +1 -1
- package/bizar-dash/dist/assets/{Textarea-xnAybFGd.js → Textarea-BfXGMXQ7.js} +1 -1
- package/bizar-dash/dist/assets/{Textarea-xnAybFGd.js.map → Textarea-BfXGMXQ7.js.map} +1 -1
- package/bizar-dash/dist/assets/{UpdateView-BUAEcRCX.js → UpdateView-BKx3u9X8.js} +1 -1
- package/bizar-dash/dist/assets/{UpdateView-BUAEcRCX.js.map → UpdateView-BKx3u9X8.js.map} +1 -1
- package/bizar-dash/dist/assets/{UsageView-DMFbBOfH.js → UsageView-M01G6bZQ.js} +1 -1
- package/bizar-dash/dist/assets/{UsageView-DMFbBOfH.js.map → UsageView-M01G6bZQ.js.map} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-C-t1U2cQ.js → ViewHeader-BsnaspKw.js} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-C-t1U2cQ.js.map → ViewHeader-BsnaspKw.js.map} +1 -1
- package/bizar-dash/dist/assets/VoiceView-rWE8vziD.js +1 -0
- package/bizar-dash/dist/assets/{VoiceView-aoPVT6LJ.js.map → VoiceView-rWE8vziD.js.map} +1 -1
- package/bizar-dash/dist/assets/{brain-DhAzcHUk.js → brain-D7k5s8vH.js} +1 -1
- package/bizar-dash/dist/assets/{brain-DhAzcHUk.js.map → brain-D7k5s8vH.js.map} +1 -1
- package/bizar-dash/dist/assets/{calendar-B9Wbemh7.js → calendar-CAZoDd-l.js} +1 -1
- package/bizar-dash/dist/assets/{calendar-B9Wbemh7.js.map → calendar-CAZoDd-l.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-6NJF_Xl6.js → circle-D99cZJBr.js} +1 -1
- package/bizar-dash/dist/assets/{circle-6NJF_Xl6.js.map → circle-D99cZJBr.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-Dz8lGfCZ.js → circle-alert-QQTU4Quz.js} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-Dz8lGfCZ.js.map → circle-alert-QQTU4Quz.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-check-DFB50ojt.js → circle-check-BMbe7Kkr.js} +1 -1
- package/bizar-dash/dist/assets/{circle-check-DFB50ojt.js.map → circle-check-BMbe7Kkr.js.map} +1 -1
- package/bizar-dash/dist/assets/{clock-ClVA6-hQ.js → clock-OtT5mvF3.js} +1 -1
- package/bizar-dash/dist/assets/{clock-ClVA6-hQ.js.map → clock-OtT5mvF3.js.map} +1 -1
- package/bizar-dash/dist/assets/{download-BvJddD8D.js → download-B-mPX5P_.js} +1 -1
- package/bizar-dash/dist/assets/{download-BvJddD8D.js.map → download-B-mPX5P_.js.map} +1 -1
- package/bizar-dash/dist/assets/{external-link-DvL89gaZ.js → external-link-DPDQM1YO.js} +1 -1
- package/bizar-dash/dist/assets/{external-link-DvL89gaZ.js.map → external-link-DPDQM1YO.js.map} +1 -1
- package/bizar-dash/dist/assets/{file-text-BOroDtZE.js → file-text-BsCrv5aP.js} +1 -1
- package/bizar-dash/dist/assets/{file-text-BOroDtZE.js.map → file-text-BsCrv5aP.js.map} +1 -1
- package/bizar-dash/dist/assets/{filter-DwPjMRQt.js → filter-Do63x17E.js} +1 -1
- package/bizar-dash/dist/assets/{filter-DwPjMRQt.js.map → filter-Do63x17E.js.map} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-TDb1inux.js → git-pull-request-CpRAmERC.js} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-TDb1inux.js.map → git-pull-request-CpRAmERC.js.map} +1 -1
- package/bizar-dash/dist/assets/main-BRmJZcHt.js +277 -0
- package/bizar-dash/dist/assets/main-BRmJZcHt.js.map +1 -0
- package/bizar-dash/dist/assets/main-D0TY0myE.css +1 -0
- package/bizar-dash/dist/assets/{network-BcCoCzIY.js → network-DJnHwHX3.js} +1 -1
- package/bizar-dash/dist/assets/{network-BcCoCzIY.js.map → network-DJnHwHX3.js.map} +1 -1
- package/bizar-dash/dist/assets/{pause-BllItT2_.js → pause-HitDUnk_.js} +1 -1
- package/bizar-dash/dist/assets/{pause-BllItT2_.js.map → pause-HitDUnk_.js.map} +1 -1
- package/bizar-dash/dist/assets/{pencil-DAwM-CC3.js → pencil-Dkks7eIC.js} +1 -1
- package/bizar-dash/dist/assets/{pencil-DAwM-CC3.js.map → pencil-Dkks7eIC.js.map} +1 -1
- package/bizar-dash/dist/assets/{play-mJh67AXo.js → play-blqh0msT.js} +1 -1
- package/bizar-dash/dist/assets/{play-mJh67AXo.js.map → play-blqh0msT.js.map} +1 -1
- package/bizar-dash/dist/assets/{plug-BjfntCMC.js → plug-DVvSSe40.js} +1 -1
- package/bizar-dash/dist/assets/{plug-BjfntCMC.js.map → plug-DVvSSe40.js.map} +1 -1
- package/bizar-dash/dist/assets/{plus-Cm6-fo14.js → plus-Cps-8lcG.js} +1 -1
- package/bizar-dash/dist/assets/{plus-Cm6-fo14.js.map → plus-Cps-8lcG.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-CXN9y2KV.js → power-DEX4_Xoa.js} +1 -1
- package/bizar-dash/dist/assets/{power-CXN9y2KV.js.map → power-DEX4_Xoa.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-off-DUZqwMf9.js → power-off-upZ4xjaG.js} +1 -1
- package/bizar-dash/dist/assets/{power-off-DUZqwMf9.js.map → power-off-upZ4xjaG.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-DA8_IB9l.js → refresh-ccw-DN_zCB1h.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-DA8_IB9l.js.map → refresh-ccw-DN_zCB1h.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-DwlP59en.js → refresh-cw-KGm5eQgv.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-DwlP59en.js.map → refresh-cw-KGm5eQgv.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-DMTASfAn.js → rotate-ccw-D5fkDRgk.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-DMTASfAn.js.map → rotate-ccw-D5fkDRgk.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-BDX5SE2s.js → rotate-cw-CClSVUaX.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-BDX5SE2s.js.map → rotate-cw-CClSVUaX.js.map} +1 -1
- package/bizar-dash/dist/assets/{save-Y0jPK5D6.js → save-BY4ViPku.js} +1 -1
- package/bizar-dash/dist/assets/{save-Y0jPK5D6.js.map → save-BY4ViPku.js.map} +1 -1
- package/bizar-dash/dist/assets/{send-C8wwPHhR.js → send-CaOL1yQD.js} +1 -1
- package/bizar-dash/dist/assets/{send-C8wwPHhR.js.map → send-CaOL1yQD.js.map} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-DEvq9UG0.js → shield-alert-DA9K6uZO.js} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-DEvq9UG0.js.map → shield-alert-DA9K6uZO.js.map} +1 -1
- package/bizar-dash/dist/assets/{trash-2-D6qePV_q.js → trash-2-B_Y6HrfN.js} +1 -1
- package/bizar-dash/dist/assets/{trash-2-D6qePV_q.js.map → trash-2-B_Y6HrfN.js.map} +1 -1
- package/bizar-dash/dist/assets/{trending-up-BZzo_1ic.js → trending-up-qKTUQKIT.js} +1 -1
- package/bizar-dash/dist/assets/{trending-up-BZzo_1ic.js.map → trending-up-qKTUQKIT.js.map} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-B2oHbmoh.js → triangle-alert-BeY8LAv6.js} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-B2oHbmoh.js.map → triangle-alert-BeY8LAv6.js.map} +1 -1
- package/bizar-dash/dist/assets/{upload-Dy59aZn6.js → upload-BZCtmqIh.js} +1 -1
- package/bizar-dash/dist/assets/{upload-Dy59aZn6.js.map → upload-BZCtmqIh.js.map} +1 -1
- package/bizar-dash/dist/assets/{zap-DENVhJnO.js → zap-Bz1Z8y1Q.js} +1 -1
- package/bizar-dash/dist/assets/{zap-DENVhJnO.js.map → zap-Bz1Z8y1Q.js.map} +1 -1
- package/bizar-dash/dist/index.html +2 -2
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/web/v8/shell/Sidebar.tsx +41 -31
- package/bizar-dash/src/web/v8/shell/Topbar.tsx +63 -23
- package/bizar-dash/src/web/v8/ui/feedback/NotificationsPopover.tsx +3 -0
- package/bizar-dash/src/web/v8/ui/feedback/useFocusTrap.ts +58 -0
- package/bizar-dash/src/web/v8/ui/navigation/CommandPalette.tsx +1 -0
- package/bizar-dash/src/web/v8/ui/styles/tokens.css +21 -0
- package/bizar-dash/src/web/v8/views/Artifacts/ClaudeArtifactView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Auth/AuthView.tsx +10 -6
- package/bizar-dash/src/web/v8/views/BackgroundJobs/BackgroundJobsView.tsx +38 -13
- package/bizar-dash/src/web/v8/views/ClaudeSessions/ClaudeSessionDetail.tsx +16 -5
- package/bizar-dash/src/web/v8/views/LightRAG/LightRAGView.tsx +23 -2
- package/bizar-dash/src/web/v8/views/Schedules/SchedulesView.tsx +48 -13
- package/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +3 -3
- package/bizar-dash/tests/auth-inputs-labels.test.mjs +45 -0
- package/bizar-dash/tests/background-jobs-action-labels.test.mjs +41 -0
- package/bizar-dash/tests/background-jobs-states.test.mjs +80 -0
- package/bizar-dash/tests/banner-tones.test.mjs +50 -0
- package/bizar-dash/tests/callout-tokens.test.mjs +30 -0
- package/bizar-dash/tests/claude-session-detail-states.test.mjs +67 -0
- package/bizar-dash/tests/components/BackgroundJobsSkeleton.test.tsx +38 -0
- package/bizar-dash/tests/density-tokens.test.mjs +46 -0
- package/bizar-dash/tests/doctor-route-shape.test.mjs +67 -0
- package/bizar-dash/tests/errorstate-retry.test.mjs +42 -0
- package/bizar-dash/tests/lightrag-skeleton.test.mjs +31 -0
- package/bizar-dash/tests/lightrag-states.test.mjs +60 -0
- package/bizar-dash/tests/modal-focus-trap.test.mjs +114 -0
- package/bizar-dash/tests/orphan-tests-audit.test.mjs +80 -0
- package/bizar-dash/tests/palette-keyboard-nav.test.mjs +123 -0
- package/bizar-dash/tests/schedules-skeleton.test.mjs +25 -0
- package/bizar-dash/tests/schedules-states.test.mjs +67 -0
- package/bizar-dash/tests/sidebar-collapse-animation.test.mjs +37 -0
- package/bizar-dash/tests/sidebar-section-styles.test.mjs +55 -0
- package/bizar-dash/tests/skeleton-height.test.mjs +47 -0
- package/bizar-dash/tests/space-tokens.test.mjs +36 -0
- package/bizar-dash/tests/stattile-loading.test.mjs +28 -0
- package/bizar-dash/tests/topbar-popover-styles.test.mjs +53 -0
- package/bizar-dash/tests/update-channels.test.mjs +67 -0
- package/package.json +1 -1
- package/packages/sdk/${HOME}/.bizar_home/memory/projects/sdk/sessions/2026-07-16-e16c2f59.md +14 -0
- package/packages/sdk/.bizar/learning/instincts.jsonl +5 -0
- package/packages/sdk/package.json +1 -1
- package/scripts/loop-log.txt +29 -0
- package/scripts/loop-tasks.md +79 -0
- package/scripts/overnight-loop.mjs +60 -0
- package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js +0 -21
- package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js.map +0 -1
- package/bizar-dash/dist/assets/AuthView-D4frSShw.js.map +0 -1
- package/bizar-dash/dist/assets/BackgroundJobsView-DEStvILz.js +0 -1
- package/bizar-dash/dist/assets/BackgroundJobsView-DEStvILz.js.map +0 -1
- package/bizar-dash/dist/assets/ClaudeSessionsView-BprGo67K.js +0 -1
- package/bizar-dash/dist/assets/ClaudeSessionsView-BprGo67K.js.map +0 -1
- package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js +0 -1
- package/bizar-dash/dist/assets/LightRAGView-DvqzQoBp.js +0 -6
- package/bizar-dash/dist/assets/LightRAGView-DvqzQoBp.js.map +0 -1
- package/bizar-dash/dist/assets/SchedulesView-o9AtIsH9.js +0 -1
- package/bizar-dash/dist/assets/SchedulesView-o9AtIsH9.js.map +0 -1
- package/bizar-dash/dist/assets/SettingsView-2HSFJPPK.js.map +0 -1
- package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js +0 -1
- package/bizar-dash/dist/assets/main-B7D_IMTh.css +0 -1
- package/bizar-dash/dist/assets/main-BURAlktW.js +0 -277
- package/bizar-dash/dist/assets/main-BURAlktW.js.map +0 -1
- package/bizar-dash/tests/chat-session-create.test.mjs +0 -391
- package/bizar-dash/tests/chat-session-stream.test.mjs +0 -308
- package/bizar-dash/tests/cline-runner.test.mjs +0 -172
- package/bizar-dash/tests/cline-sessions-detail.test.mjs +0 -434
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Banner-
|
|
1
|
+
{"version":3,"file":"Banner-Du-3l05O.js","sources":["../../src/web/v8/ui/feedback/Banner.tsx"],"sourcesContent":["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});"],"names":["Banner","forwardRef","props","ref","tone","children","action","className","rest","jsxs","cx","jsx"],"mappings":"qFAeO,MAAMA,EAASC,EAAAA,WAAwC,SAAgBC,EAAOC,EAAK,CACxF,KAAM,CAAE,KAAAC,EAAO,OAAQ,SAAAC,EAAU,OAAAC,EAAQ,UAAAC,EAAW,GAAGC,GAASN,EAChE,OACEO,EAAAA,KAAC,MAAA,CACC,IAAAN,EACA,KAAMC,IAAS,SAAW,QAAU,SACpC,UAAWM,EAAG,YAAa,cAAcN,CAAI,GAAIG,CAAS,EAC1D,MAAO,CACL,QAAS,OACT,WAAY,SACZ,IAAK,iBACL,QAAS,gCACT,WAAY,6BAA6BH,CAAI,0BAC7C,aAAc,0BACd,SAAU,eACV,MAAO,WAAA,EAER,GAAGI,EAEJ,SAAA,CAAAG,MAAC,MAAA,CAAI,MAAO,CAAE,KAAM,EAAG,SAAU,GAAM,SAAAN,EAAS,EAC/CC,IAAW,QAAaK,MAAC,MAAA,CAAI,MAAO,CAAE,WAAY,CAAA,EAAM,SAAAL,CAAA,CAAO,CAAA,CAAA,CAAA,CAGtE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as d,j as o}from"./cmdk-C3F6LD6N.js";import{g as n}from"./main-
|
|
1
|
+
import{r as d,j as o}from"./cmdk-C3F6LD6N.js";import{g as n}from"./main-BRmJZcHt.js";const f={default:{background:"var(--surface-1)",border:"1px solid var(--border)",boxShadow:"none"},elevated:{background:"var(--surface-1)",border:"1px solid var(--border)",boxShadow:"var(--shadow-2)"},ghost:{background:"transparent",border:"1px solid transparent",boxShadow:"none"},outlined:{background:"var(--surface-0)",border:"1px solid var(--border)",boxShadow:"none"}},x=d.forwardRef(function(s,t){const{variant:r="default",flush:a,interactive:e,className:c,style:l,...v}=s;return o.jsx("div",{ref:t,className:n("v8-card",`v8-card--${r}`,e&&"is-interactive",c),style:{borderRadius:"var(--radius-lg)",padding:a===!0?0:"var(--density-card-pad)",cursor:e===!0?"pointer":void 0,transition:e===!0?"border-color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out), transform var(--motion-fast) var(--ease-out)":void 0,...f[r],...l},...v})}),m=d.forwardRef(function(s,t){const{title:r,description:a,action:e,className:c,style:l,...v}=s;return o.jsxs("div",{ref:t,className:n("v8-card__header",c),style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:"var(--space-3)",marginBottom:"var(--space-3)",...l},...v,children:[o.jsxs("div",{style:{flex:1,minWidth:0},children:[o.jsx("div",{style:{fontSize:"var(--fs-14)",fontWeight:600,color:"var(--fg)"},children:r}),a!==void 0&&o.jsx("div",{style:{fontSize:"var(--fs-13)",color:"var(--fg-muted)",marginTop:2},children:a})]}),e!==void 0&&o.jsx("div",{style:{flexShrink:0},children:e})]})}),b=d.forwardRef(function(s,t){const{className:r,...a}=s;return o.jsx("div",{ref:t,className:n("v8-card__body",r),...a})});d.forwardRef(function(s,t){const{className:r,style:a,...e}=s;return o.jsx("div",{ref:t,className:n("v8-card__footer",r),style:{display:"flex",alignItems:"center",justifyContent:"flex-end",gap:"var(--space-2)",marginTop:"var(--space-3)",paddingTop:"var(--space-3)",borderTop:"1px solid var(--border)",...a},...e})});export{x as C,m as a,b};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card-
|
|
1
|
+
{"version":3,"file":"Card-Clkvh43Q.js","sources":["../../src/web/v8/ui/data/Card.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\n/**\n * Card — the v8 surface primitive.\n *\n * Variants:\n * - default: bordered, --surface-1 background, used for kanban cards, settings groups.\n * - elevated: --surface-1 background + shadow, used for popovers/dropdowns hovering over content.\n * - ghost: no border, transparent background, used inside other Cards (nested).\n * - outlined: thicker border, --surface-0 background, used for group containers.\n *\n * All variants have a consistent --radius-lg corner and pad via --density-card-pad.\n * The header / body / footer slots are conventions — pass any children you want.\n */\nexport type CardVariant = 'default' | 'elevated' | 'ghost' | 'outlined';\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n variant?: CardVariant;\n /** Removes padding so the child fills the card edge-to-edge. */\n flush?: boolean;\n /** Adds hover lift + cursor pointer for clickable cards. */\n interactive?: boolean;\n children?: ReactNode;\n}\n\nconst VARIANT_STYLE: Record<CardVariant, React.CSSProperties> = {\n default: {\n background: 'var(--surface-1)',\n border: '1px solid var(--border)',\n boxShadow: 'none',\n },\n elevated: {\n background: 'var(--surface-1)',\n border: '1px solid var(--border)',\n boxShadow: 'var(--shadow-2)',\n },\n ghost: {\n background: 'transparent',\n border: '1px solid transparent',\n boxShadow: 'none',\n },\n outlined: {\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n boxShadow: 'none',\n },\n};\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(props, ref) {\n const { variant = 'default', flush, interactive, className, style, ...rest } = props;\n return (\n <div\n ref={ref}\n className={cx('v8-card', `v8-card--${variant}`, interactive && 'is-interactive', className)}\n style={{\n borderRadius: 'var(--radius-lg)',\n padding: flush === true ? 0 : 'var(--density-card-pad)',\n cursor: interactive === true ? 'pointer' : undefined,\n transition: interactive === true\n ? 'border-color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out), transform var(--motion-fast) var(--ease-out)'\n : undefined,\n ...VARIANT_STYLE[variant],\n ...style,\n }}\n {...rest}\n />\n );\n});\n\n/** Card header — title row + optional actions. */\nexport interface CardHeaderProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n title: ReactNode;\n description?: ReactNode;\n action?: ReactNode;\n}\n\nexport const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(function CardHeader(\n props,\n ref,\n) {\n const { title, description, action, className, style, ...rest } = props;\n return (\n <div\n ref={ref}\n className={cx('v8-card__header', className)}\n style={{\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n gap: 'var(--space-3)',\n marginBottom: 'var(--space-3)',\n ...style,\n }}\n {...rest}\n >\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontSize: 'var(--fs-14)', fontWeight: 600, color: 'var(--fg)' }}>{title}</div>\n {description !== undefined && (\n <div style={{ fontSize: 'var(--fs-13)', color: 'var(--fg-muted)', marginTop: 2 }}>\n {description}\n </div>\n )}\n </div>\n {action !== undefined && <div style={{ flexShrink: 0 }}>{action}</div>}\n </div>\n );\n});\n\n/** Card body — main content slot. */\nexport const CardBody = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n function CardBody(props, ref) {\n const { className, ...rest } = props;\n return <div ref={ref} className={cx('v8-card__body', className)} {...rest} />;\n },\n);\n\n/** Card footer — typically action buttons right-aligned. */\nexport const CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n function CardFooter(props, ref) {\n const { className, style, ...rest } = props;\n return (\n <div\n ref={ref}\n className={cx('v8-card__footer', className)}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: 'var(--space-2)',\n marginTop: 'var(--space-3)',\n paddingTop: 'var(--space-3)',\n borderTop: '1px solid var(--border)',\n ...style,\n }}\n {...rest}\n />\n );\n },\n);"],"names":["VARIANT_STYLE","Card","forwardRef","props","ref","variant","flush","interactive","className","style","rest","jsx","cx","CardHeader","title","description","action","jsxs","CardBody"],"mappings":"qFA0BA,MAAMA,EAA0D,CAC9D,QAAS,CACP,WAAY,mBACZ,OAAQ,0BACR,UAAW,MAAA,EAEb,SAAU,CACR,WAAY,mBACZ,OAAQ,0BACR,UAAW,iBAAA,EAEb,MAAO,CACL,WAAY,cACZ,OAAQ,wBACR,UAAW,MAAA,EAEb,SAAU,CACR,WAAY,mBACZ,OAAQ,0BACR,UAAW,MAAA,CAEf,EAEaC,EAAOC,EAAAA,WAAsC,SAAcC,EAAOC,EAAK,CAClF,KAAM,CAAE,QAAAC,EAAU,UAAW,MAAAC,EAAO,YAAAC,EAAa,UAAAC,EAAW,MAAAC,EAAO,GAAGC,CAAA,EAASP,EAC/E,OACEQ,EAAAA,IAAC,MAAA,CACC,IAAAP,EACA,UAAWQ,EAAG,UAAW,YAAYP,CAAO,GAAIE,GAAe,iBAAkBC,CAAS,EAC1F,MAAO,CACL,aAAc,mBACd,QAASF,IAAU,GAAO,EAAI,0BAC9B,OAAQC,IAAgB,GAAO,UAAY,OAC3C,WAAYA,IAAgB,GACxB,+IACA,OACJ,GAAGP,EAAcK,CAAO,EACxB,GAAGI,CAAA,EAEJ,GAAGC,CAAA,CAAA,CAGV,CAAC,EASYG,EAAaX,EAAAA,WAA4C,SACpEC,EACAC,EACA,CACA,KAAM,CAAE,MAAAU,EAAO,YAAAC,EAAa,OAAAC,EAAQ,UAAAR,EAAW,MAAAC,EAAO,GAAGC,GAASP,EAClE,OACEc,EAAAA,KAAC,MAAA,CACC,IAAAb,EACA,UAAWQ,EAAG,kBAAmBJ,CAAS,EAC1C,MAAO,CACL,QAAS,OACT,WAAY,aACZ,eAAgB,gBAChB,IAAK,iBACL,aAAc,iBACd,GAAGC,CAAA,EAEJ,GAAGC,EAEJ,SAAA,CAAAO,OAAC,OAAI,MAAO,CAAE,KAAM,EAAG,SAAU,GAC/B,SAAA,CAAAN,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,WAAY,IAAK,MAAO,WAAA,EAAgB,SAAAG,CAAA,CAAM,EACrFC,IAAgB,QACfJ,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,MAAO,kBAAmB,UAAW,CAAA,EAC1E,SAAAI,CAAA,CACH,CAAA,EAEJ,EACCC,IAAW,QAAaL,MAAC,MAAA,CAAI,MAAO,CAAE,WAAY,CAAA,EAAM,SAAAK,CAAA,CAAO,CAAA,CAAA,CAAA,CAGtE,CAAC,EAGYE,EAAWhB,EAAAA,WACtB,SAAkBC,EAAOC,EAAK,CAC5B,KAAM,CAAE,UAAAI,EAAW,GAAGE,CAAA,EAASP,EAC/B,OAAOQ,MAAC,OAAI,IAAAP,EAAU,UAAWQ,EAAG,gBAAiBJ,CAAS,EAAI,GAAGE,EAAM,CAC7E,CACF,EAG0BR,EAAAA,WACxB,SAAoBC,EAAOC,EAAK,CAC9B,KAAM,CAAE,UAAAI,EAAW,MAAAC,EAAO,GAAGC,GAASP,EACtC,OACEQ,EAAAA,IAAC,MAAA,CACC,IAAAP,EACA,UAAWQ,EAAG,kBAAmBJ,CAAS,EAC1C,MAAO,CACL,QAAS,OACT,WAAY,SACZ,eAAgB,WAChB,IAAK,iBACL,UAAW,iBACX,WAAY,iBACZ,UAAW,0BACX,GAAGC,CAAA,EAEJ,GAAGC,CAAA,CAAA,CAGV,CACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as e,r as n}from"./cmdk-C3F6LD6N.js";import{d as q,S as E,I as k,B as S,i as P,F as O,u as N,a as K,G,h as $}from"./main-
|
|
1
|
+
import{j as e,r as n}from"./cmdk-C3F6LD6N.js";import{d as q,S as E,I as k,B as S,i as P,F as O,u as N,a as K,G,h as $}from"./main-BRmJZcHt.js";import{V as L}from"./ViewHeader-BsnaspKw.js";import{C as A,b as B}from"./Card-Clkvh43Q.js";import{T as Y}from"./Textarea-BfXGMXQ7.js";import{E as _}from"./EmptyState-ccT__JZG.js";import{E as Q,M as F}from"./MessageBubble-CrCJ0SYG.js";import{I as M}from"./Input-DV-vdaV8.js";import{S as U,a as X,b as Z}from"./Sheet-BwMVGN-8.js";import{R as ee}from"./refresh-cw-KGm5eQgv.js";import{S as te}from"./send-CaOL1yQD.js";/**
|
|
2
2
|
* @license lucide-react v0.460.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatView-CkNS0SD8.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/message-square-plus.js","../../src/web/v8/ui/chat/EventStream.tsx","../../src/web/v8/views/ClaudeSessions/NewSessionModal.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 * NewSessionModal — shared new-session Sheet, extracted from\n * ClaudeSessionsView so ChatView can reuse the same form.\n */\n\nimport { useState } from 'react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface NewSessionModalProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCreated: (id: string) => void;\n}\n\nexport function NewSessionModal({ open, onOpenChange, onCreated }: NewSessionModalProps): JSX.Element {\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent side=\"right\" title=\"New Claude session\" description=\"Spawn a Claude Code session via the runner.\">\n <NewSessionForm\n onCreated={(id) => {\n onOpenChange(false);\n onCreated(id);\n }}\n onCancel={() => onOpenChange(false)}\n />\n </SheetContent>\n </Sheet>\n );\n}\n\ninterface NewSessionFormProps {\n onCreated: (id: string) => void;\n onCancel: () => void;\n}\n\nexport function NewSessionForm({ onCreated, onCancel }: NewSessionFormProps): JSX.Element {\n const [title, setTitle] = useState<string>('');\n const [agent, setAgent] = useState<string>('general');\n const [prompt, setPrompt] = useState<string>('');\n const [directory, setDirectory] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (): Promise<void> => {\n if (!agent.trim() || !prompt.trim() || busy) return;\n setBusy(true);\n setError(null);\n try {\n const res = await fetchJson<{ id: string }>('/api/claude-sessions/new', {\n method: 'POST',\n body: {\n title: title.trim() || null,\n agent: agent.trim(),\n prompt: prompt.trim(),\n directory: directory.trim() || undefined,\n },\n });\n onCreated(res.id);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Title (optional)</span>\n <Input\n value={title}\n data-testid=\"claude-sessions-new-title\"\n onChange={(e) => setTitle((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Agent</span>\n <Input\n value={agent}\n data-testid=\"claude-sessions-new-agent\"\n onChange={(e) => setAgent((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Seed prompt</span>\n <textarea\n value={prompt}\n rows={4}\n data-testid=\"claude-sessions-new-prompt\"\n onChange={(e) => setPrompt(e.target.value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-sans)',\n fontSize: 'var(--fs-13)',\n resize: 'vertical',\n }}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Working directory (optional)</span>\n <Input\n value={directory}\n data-testid=\"claude-sessions-new-directory\"\n onChange={(e) => setDirectory((e.target as HTMLInputElement).value)}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" data-testid=\"claude-sessions-new-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel} data-testid=\"claude-sessions-new-cancel\">Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={() => void submit()}\n disabled={busy || !agent.trim() || !prompt.trim()}\n data-testid=\"claude-sessions-new-submit\"\n >\n Create\n </Button>\n </Inline>\n </Stack>\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';\nimport { NewSessionModal } from '../ClaudeSessions/NewSessionModal.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 const [newSessionOpen, setNewSessionOpen] = useState<boolean>(false);\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={() => setNewSessionOpen(true)} 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\n <NewSessionModal\n open={newSessionOpen}\n onOpenChange={setNewSessionOpen}\n onCreated={(id) => {\n setActiveId(id);\n void payload.refetch();\n void sessionsPayload.refetch();\n }}\n />\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","NewSessionModal","open","onOpenChange","onCreated","jsx","Sheet","SheetContent","NewSessionForm","id","onCancel","title","setTitle","useState","agent","setAgent","prompt","setPrompt","directory","setDirectory","busy","setBusy","error","setError","submit","res","fetchJson","FetchError","jsxs","Stack","Input","e","Inline","SheetClose","Button","ChatView","payload","useFetch","sessionsPayload","activeId","setActiveId","transcript","setTranscript","streaming","setStreaming","draft","setDraft","confirmDeleteId","setConfirmDeleteId","newSessionOpen","setNewSessionOpen","useEffect","_a","m","s","sessions","useMemo","onChange","useCallback","msg","useWsMessage","send","text","optimistic","prev","ctrl","chunk","cur","parsed","regenerate","audit","dropSession","ViewHeader","RefreshCw","ShieldCheck","Card","CardBody","Skeleton","EmptyState","isActive","isConfirmingDelete","EmptyTranscript","MessageBubble","Send","Textarea"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"ChatView-BTjb3mIh.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/message-square-plus.js","../../src/web/v8/ui/chat/EventStream.tsx","../../src/web/v8/views/ClaudeSessions/NewSessionModal.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 * NewSessionModal — shared new-session Sheet, extracted from\n * ClaudeSessionsView so ChatView can reuse the same form.\n */\n\nimport { useState } from 'react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface NewSessionModalProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCreated: (id: string) => void;\n}\n\nexport function NewSessionModal({ open, onOpenChange, onCreated }: NewSessionModalProps): JSX.Element {\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent side=\"right\" title=\"New Claude session\" description=\"Spawn a Claude Code session via the runner.\">\n <NewSessionForm\n onCreated={(id) => {\n onOpenChange(false);\n onCreated(id);\n }}\n onCancel={() => onOpenChange(false)}\n />\n </SheetContent>\n </Sheet>\n );\n}\n\ninterface NewSessionFormProps {\n onCreated: (id: string) => void;\n onCancel: () => void;\n}\n\nexport function NewSessionForm({ onCreated, onCancel }: NewSessionFormProps): JSX.Element {\n const [title, setTitle] = useState<string>('');\n const [agent, setAgent] = useState<string>('general');\n const [prompt, setPrompt] = useState<string>('');\n const [directory, setDirectory] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (): Promise<void> => {\n if (!agent.trim() || !prompt.trim() || busy) return;\n setBusy(true);\n setError(null);\n try {\n const res = await fetchJson<{ id: string }>('/api/claude-sessions/new', {\n method: 'POST',\n body: {\n title: title.trim() || null,\n agent: agent.trim(),\n prompt: prompt.trim(),\n directory: directory.trim() || undefined,\n },\n });\n onCreated(res.id);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Title (optional)</span>\n <Input\n value={title}\n data-testid=\"claude-sessions-new-title\"\n onChange={(e) => setTitle((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Agent</span>\n <Input\n value={agent}\n data-testid=\"claude-sessions-new-agent\"\n onChange={(e) => setAgent((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Seed prompt</span>\n <textarea\n value={prompt}\n rows={4}\n data-testid=\"claude-sessions-new-prompt\"\n onChange={(e) => setPrompt(e.target.value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-sans)',\n fontSize: 'var(--fs-13)',\n resize: 'vertical',\n }}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Working directory (optional)</span>\n <Input\n value={directory}\n data-testid=\"claude-sessions-new-directory\"\n onChange={(e) => setDirectory((e.target as HTMLInputElement).value)}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" data-testid=\"claude-sessions-new-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel} data-testid=\"claude-sessions-new-cancel\">Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={() => void submit()}\n disabled={busy || !agent.trim() || !prompt.trim()}\n data-testid=\"claude-sessions-new-submit\"\n >\n Create\n </Button>\n </Inline>\n </Stack>\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';\nimport { NewSessionModal } from '../ClaudeSessions/NewSessionModal.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 const [newSessionOpen, setNewSessionOpen] = useState<boolean>(false);\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={() => setNewSessionOpen(true)} 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\n <NewSessionModal\n open={newSessionOpen}\n onOpenChange={setNewSessionOpen}\n onCreated={(id) => {\n setActiveId(id);\n void payload.refetch();\n void sessionsPayload.refetch();\n }}\n />\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","NewSessionModal","open","onOpenChange","onCreated","jsx","Sheet","SheetContent","NewSessionForm","id","onCancel","title","setTitle","useState","agent","setAgent","prompt","setPrompt","directory","setDirectory","busy","setBusy","error","setError","submit","res","fetchJson","FetchError","jsxs","Stack","Input","e","Inline","SheetClose","Button","ChatView","payload","useFetch","sessionsPayload","activeId","setActiveId","transcript","setTranscript","streaming","setStreaming","draft","setDraft","confirmDeleteId","setConfirmDeleteId","newSessionOpen","setNewSessionOpen","useEffect","_a","m","s","sessions","useMemo","onChange","useCallback","msg","useWsMessage","send","text","optimistic","prev","ctrl","chunk","cur","parsed","regenerate","audit","dropSession","ViewHeader","RefreshCw","ShieldCheck","Card","CardBody","Skeleton","EmptyState","isActive","isConfirmingDelete","EmptyTranscript","MessageBubble","Send","Textarea"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as u,j as o}from"./cmdk-C3F6LD6N.js";import{X as h,g as p}from"./main-
|
|
1
|
+
import{r as u,j as o}from"./cmdk-C3F6LD6N.js";import{X as h,g as p}from"./main-BRmJZcHt.js";const f={neutral:"var(--surface-1)",info:"color-mix(in oklch, var(--info) 14%, var(--surface-1))",success:"color-mix(in oklch, var(--success) 14%, var(--surface-1))",warning:"color-mix(in oklch, var(--warning) 14%, var(--surface-1))",danger:"color-mix(in oklch, var(--danger) 14%, var(--surface-1))",accent:"color-mix(in oklch, var(--accent) 14%, var(--surface-1))"},m={neutral:"var(--border)",info:"color-mix(in oklch, var(--info) 30%, var(--border))",success:"color-mix(in oklch, var(--success) 30%, var(--border))",warning:"color-mix(in oklch, var(--warning) 30%, var(--border))",danger:"color-mix(in oklch, var(--danger) 30%, var(--border))",accent:"color-mix(in oklch, var(--accent) 30%, var(--border))"},k=u.forwardRef(function(n,c){const{tone:e="neutral",selected:r,onRemove:a,children:i,className:t,style:s,...l}=n,d=r!==void 0||a!==void 0;return o.jsxs("span",{ref:c,className:p("v8-chip",`v8-chip--${e}`,r===!0&&"is-selected",t),style:{display:"inline-flex",alignItems:"center",gap:"var(--space-1)",height:24,padding:"0 8px",background:r===!0?"color-mix(in oklch, var(--accent) 18%, var(--surface-1))":f[e],border:"1px solid",borderColor:r===!0?"var(--accent)":m[e],borderRadius:"var(--radius-pill)",fontSize:"var(--fs-12)",fontWeight:500,color:r===!0?"var(--accent)":"var(--fg)",cursor:d===!0?"pointer":"default",whiteSpace:"nowrap",...s},...l,children:[i,a!==void 0&&o.jsx("button",{type:"button",onClick:v=>{v.stopPropagation(),a()},"aria-label":"Remove",style:{display:"inline-flex",alignItems:"center",justifyContent:"center",width:14,height:14,marginLeft:2,marginRight:-4,padding:0,background:"transparent",border:0,borderRadius:"var(--radius-sm)",color:"var(--fg-muted)",cursor:"pointer"},children:o.jsx(h,{size:10,"aria-hidden":"true"})})]})});export{k as C};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chip-
|
|
1
|
+
{"version":3,"file":"Chip-B7ovcm01.js","sources":["../../src/web/v8/ui/data/Chip.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { X } from 'lucide-react';\nimport { cx } from '../utils/cx.js';\n\n/**\n * Chip — filter pill with an optional remove button.\n *\n * Different from Badge: Badge is a status indicator (read-only).\n * Chip is interactive — clickable for selection, removable for filters.\n */\n\nexport interface ChipProps extends HTMLAttributes<HTMLSpanElement> {\n /** Visual tone. */\n tone?: 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'accent';\n /** When true, render with selected styling (used for filter chips). */\n selected?: boolean;\n /** When provided, render a close button that invokes this handler. */\n onRemove?: () => void;\n children: ReactNode;\n}\n\nconst TONE_BG: Record<NonNullable<ChipProps['tone']>, string> = {\n neutral: 'var(--surface-1)',\n info: 'color-mix(in oklch, var(--info) 14%, var(--surface-1))',\n success: 'color-mix(in oklch, var(--success) 14%, var(--surface-1))',\n warning: 'color-mix(in oklch, var(--warning) 14%, var(--surface-1))',\n danger: 'color-mix(in oklch, var(--danger) 14%, var(--surface-1))',\n accent: 'color-mix(in oklch, var(--accent) 14%, var(--surface-1))',\n};\n\nconst TONE_BORDER: Record<NonNullable<ChipProps['tone']>, string> = {\n neutral: 'var(--border)',\n info: 'color-mix(in oklch, var(--info) 30%, var(--border))',\n success: 'color-mix(in oklch, var(--success) 30%, var(--border))',\n warning: 'color-mix(in oklch, var(--warning) 30%, var(--border))',\n danger: 'color-mix(in oklch, var(--danger) 30%, var(--border))',\n accent: 'color-mix(in oklch, var(--accent) 30%, var(--border))',\n};\n\nexport const Chip = forwardRef<HTMLSpanElement, ChipProps>(function Chip(props, ref) {\n const { tone = 'neutral', selected, onRemove, children, className, style, ...rest } = props;\n const isInteractive = selected !== undefined || onRemove !== undefined;\n return (\n <span\n ref={ref}\n className={cx('v8-chip', `v8-chip--${tone}`, selected === true && 'is-selected', className)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: 'var(--space-1)',\n height: 24,\n padding: '0 8px',\n background: selected === true ? `color-mix(in oklch, var(--accent) 18%, var(--surface-1))` : TONE_BG[tone],\n border: '1px solid',\n borderColor: selected === true ? 'var(--accent)' : TONE_BORDER[tone],\n borderRadius: 'var(--radius-pill)',\n fontSize: 'var(--fs-12)',\n fontWeight: 500,\n color: selected === true ? 'var(--accent)' : 'var(--fg)',\n cursor: isInteractive === true ? 'pointer' : 'default',\n whiteSpace: 'nowrap',\n ...style,\n }}\n {...rest}\n >\n {children}\n {onRemove !== undefined && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n aria-label=\"Remove\"\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 14,\n height: 14,\n marginLeft: 2,\n marginRight: -4,\n padding: 0,\n background: 'transparent',\n border: 0,\n borderRadius: 'var(--radius-sm)',\n color: 'var(--fg-muted)',\n cursor: 'pointer',\n }}\n >\n <X size={10} aria-hidden=\"true\" />\n </button>\n )}\n </span>\n );\n});"],"names":["TONE_BG","TONE_BORDER","Chip","forwardRef","props","ref","tone","selected","onRemove","children","className","style","rest","isInteractive","jsxs","cx","jsx","e","X"],"mappings":"4FAqBA,MAAMA,EAA0D,CAC9D,QAAS,mBACT,KAAM,yDACN,QAAS,4DACT,QAAS,4DACT,OAAQ,2DACR,OAAQ,0DACV,EAEMC,EAA8D,CAClE,QAAS,gBACT,KAAM,sDACN,QAAS,yDACT,QAAS,yDACT,OAAQ,wDACR,OAAQ,uDACV,EAEaC,EAAOC,EAAAA,WAAuC,SAAcC,EAAOC,EAAK,CACnF,KAAM,CAAE,KAAAC,EAAO,UAAW,SAAAC,EAAU,SAAAC,EAAU,SAAAC,EAAU,UAAAC,EAAW,MAAAC,EAAO,GAAGC,CAAA,EAASR,EAChFS,EAAgBN,IAAa,QAAaC,IAAa,OAC7D,OACEM,EAAAA,KAAC,OAAA,CACC,IAAAT,EACA,UAAWU,EAAG,UAAW,YAAYT,CAAI,GAAIC,IAAa,IAAQ,cAAeG,CAAS,EAC1F,MAAO,CACL,QAAS,cACT,WAAY,SACZ,IAAK,iBACL,OAAQ,GACR,QAAS,QACT,WAAYH,IAAa,GAAO,2DAA6DP,EAAQM,CAAI,EACzG,OAAQ,YACR,YAAaC,IAAa,GAAO,gBAAkBN,EAAYK,CAAI,EACnE,aAAc,qBACd,SAAU,eACV,WAAY,IACZ,MAAOC,IAAa,GAAO,gBAAkB,YAC7C,OAAQM,IAAkB,GAAO,UAAY,UAC7C,WAAY,SACZ,GAAGF,CAAA,EAEJ,GAAGC,EAEH,SAAA,CAAAH,EACAD,IAAa,QACZQ,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAUC,GAAM,CACdA,EAAE,gBAAA,EACFT,EAAA,CACF,EACA,aAAW,SACX,MAAO,CACL,QAAS,cACT,WAAY,SACZ,eAAgB,SAChB,MAAO,GACP,OAAQ,GACR,WAAY,EACZ,YAAa,GACb,QAAS,EACT,WAAY,cACZ,OAAQ,EACR,aAAc,mBACd,MAAO,kBACP,OAAQ,SAAA,EAGV,SAAAQ,EAAAA,IAACE,EAAA,CAAE,KAAM,GAAI,cAAY,MAAA,CAAO,CAAA,CAAA,CAClC,CAAA,CAAA,CAIR,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r,j as e}from"./cmdk-C3F6LD6N.js";import{u as D,S as j,I as h,B as c,h as $,M as P,i as S,F as C,P as O}from"./main-BRmJZcHt.js";import{V as B}from"./ViewHeader-BsnaspKw.js";import{C as E,b as R}from"./Card-Clkvh43Q.js";import{I as b}from"./Input-DV-vdaV8.js";import{S as z,a as k,b as A}from"./Sheet-BwMVGN-8.js";import{E as T}from"./EmptyState-ccT__JZG.js";import{E as M}from"./ErrorState-BSqf65ka.js";import{M as N}from"./MessageBubble-CrCJ0SYG.js";import{R as F}from"./refresh-ccw-DN_zCB1h.js";import{S as V}from"./send-CaOL1yQD.js";import{P as q}from"./plus-Cps-8lcG.js";import{P as H}from"./pencil-Dkks7eIC.js";import{T as W}from"./trash-2-B_Y6HrfN.js";import"./Alert-pzFISNtS.js";import"./circle-alert-QQTU4Quz.js";import"./triangle-alert-BeY8LAv6.js";import"./circle-check-BMbe7Kkr.js";function J({sessionId:a}){var t;const p=`/api/claude-sessions/${a}/messages`,i=D(p),[u,l]=r.useState(""),[o,d]=r.useState("general"),[m,n]=r.useState(!1),[v,f]=r.useState(null),g=r.useCallback(()=>{i.refetch()},[i]),x=((t=i.data)==null?void 0:t.messages)??[],y=async()=>{const s=u.trim();if(!(!s||!o.trim()||m)){n(!0),f(null);try{await S(`/api/claude-sessions/${a}/send`,{method:"POST",body:{message:s,agent:o.trim()}}),l(""),window.setTimeout(()=>{g()},750)}catch(w){f((w instanceof C,w.message))}finally{n(!1)}}};return e.jsxs(j,{gap:3,style:{padding:"var(--space-4)"},"data-testid":`claude-session-detail-${a}`,children:[e.jsxs(h,{align:"center",justify:"between",gap:2,children:[e.jsx("strong",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)"},children:a}),e.jsxs(c,{variant:"ghost",onClick:()=>void g(),"data-testid":`claude-session-detail-refresh-${a}`,children:[e.jsx(F,{size:14,"aria-hidden":!0})," Refresh"]})]}),e.jsx(E,{variant:"default",children:e.jsx(R,{children:i.error!=null?e.jsx(M,{error:i.error,onRetry:g,description:"Failed to load session messages."}):i.loading&&x.length===0?e.jsx($,{style:{height:120}}):x.length===0?e.jsx(T,{icon:e.jsx(P,{size:28,"aria-hidden":!0}),title:"No messages yet",description:"Send a follow-up below to start the conversation.","data-testid":`claude-session-detail-empty-${a}`}):e.jsx(j,{gap:1,children:x.map(s=>e.jsx(N,{message:s},s.id||`${s.ts}-${s.role}`))})})}),v!==null&&e.jsx("span",{role:"alert","data-testid":`claude-session-detail-error-${a}`,style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:v}),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:"Agent"}),e.jsx(b,{value:o,"data-testid":`claude-session-detail-agent-${a}`,onChange:s=>d(s.target.value)})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Follow-up"}),e.jsx("textarea",{value:u,rows:4,"data-testid":`claude-session-detail-draft-${a}`,onChange:s=>l(s.target.value),style:{background:"var(--surface-0)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"var(--space-2)",color:"var(--fg)",fontFamily:"var(--font-sans)",fontSize:"var(--fs-13)",resize:"vertical"}})]}),e.jsx(h,{justify:"end",gap:2,children:e.jsxs(c,{variant:"primary",onClick:()=>void y(),disabled:m||u.trim()===""||o.trim()==="","data-testid":`claude-session-detail-send-${a}`,children:[e.jsx(V,{size:14,"aria-hidden":!0})," ",m?"Sending…":"Send"]})})]})}function ce(){var m;const a=D("/api/claude-sessions"),[p,i]=r.useState(!1),[u,l]=r.useState(null),o=((m=a.data)==null?void 0:m.sessions)??[],d=r.useCallback(()=>{a.refetch()},[a]);return e.jsxs(j,{gap:4,"data-testid":"claude-sessions-view",children:[e.jsx(B,{title:"Claude sessions",description:"Claude Code session explorer. Each row is a session directory under ~/.claude/sessions/.",actions:e.jsxs(h,{align:"center",gap:2,children:[e.jsxs(c,{variant:"ghost",onClick:()=>void d(),"data-testid":"claude-sessions-refresh",children:[e.jsx(F,{size:14,"aria-hidden":!0})," Refresh"]}),e.jsxs(c,{variant:"primary",onClick:()=>i(!0),"data-testid":"claude-sessions-new",children:[e.jsx(q,{size:14,"aria-hidden":!0})," New session"]})]})}),e.jsx(E,{variant:"default",children:e.jsx(R,{children:a.loading&&o.length===0?e.jsxs(j,{gap:2,children:[e.jsx($,{style:{height:36}}),e.jsx($,{style:{height:36}})]}):o.length===0?e.jsx(T,{icon:e.jsx(O,{size:28,"aria-hidden":!0}),title:"No Claude sessions",description:"Create one to start a multi-turn conversation with Claude Code."}):e.jsx(j,{gap:2,children:o.map(n=>e.jsx(L,{session:n,onRefresh:d,onOpen:l},n.id))})})}),e.jsx(z,{open:p,onOpenChange:i,children:e.jsx(k,{side:"right",title:"New Claude session",description:"Spawn a Claude Code session via the runner.",children:e.jsx(G,{onCreated:n=>{i(!1),d(),l(n)},onCancel:()=>i(!1)})})}),e.jsx(z,{open:u!==null,onOpenChange:n=>{n||l(null)},children:e.jsx(k,{side:"right",title:"Session detail",description:u??"",children:u!==null&&e.jsx(J,{sessionId:u})})})]})}function L({session:a,onRefresh:p,onOpen:i}){const[u,l]=r.useState(!1),[o,d]=r.useState(a.title??""),[m,n]=r.useState(!1),[v,f]=r.useState(null),g=async()=>{if(o.trim()){f(null);try{await S(`/api/claude-sessions/${a.id}`,{method:"PATCH",body:{title:o.trim()}}),l(!1),p()}catch(t){f((t instanceof C,t.message))}}},x=async t=>{f(null);try{await S(`/api/claude-sessions/${t}/resume`,{method:"POST",body:{}})}catch(s){f((s instanceof C,s.message))}},y=async()=>{f(null);try{await S(`/api/claude-sessions/${a.id}`,{method:"DELETE"}),n(!1),p()}catch(t){f((t instanceof C,t.message))}};return e.jsxs("div",{"data-testid":`claude-session-row-${a.id}`,style:{padding:"var(--space-3)",borderRadius:"var(--radius-md)",border:"1px solid var(--border)",background:"var(--surface-0)"},children:[e.jsxs(h,{align:"center",justify:"between",gap:3,children:[e.jsxs(j,{gap:1,style:{minWidth:0,flex:1},children:[u?e.jsxs(h,{gap:1,children:[e.jsx(b,{value:o,"data-testid":`claude-session-rename-input-${a.id}`,onChange:t=>d(t.target.value)}),e.jsx(c,{variant:"primary",onClick:()=>void g(),"data-testid":`claude-session-rename-submit-${a.id}`,children:"Save"}),e.jsx(c,{variant:"ghost",onClick:()=>{l(!1),d(a.title??"")},children:"Cancel"})]}):e.jsxs(h,{align:"center",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:a.title||a.id}),a.agent&&e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)",fontFamily:"var(--font-mono)"},children:["@",a.agent]})]}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:a.id}),v!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:v})]}),e.jsxs(h,{gap:1,children:[e.jsx(c,{variant:"primary",onClick:()=>void x(a.id),"data-testid":`claude-session-resume-${a.id}`,"aria-label":`Resume ${a.id}`,children:"Resume"}),e.jsx(c,{variant:"ghost",onClick:()=>i(a.id),"data-testid":`claude-session-open-${a.id}`,children:"Open"}),e.jsx(c,{variant:"ghost",onClick:()=>{l(!0),d(a.title??"")},"data-testid":`claude-session-rename-${a.id}`,"aria-label":`Rename session ${a.id}`,children:e.jsx(H,{size:14,"aria-hidden":!0})}),e.jsx(c,{variant:"ghost",onClick:()=>n(t=>!t),"data-testid":`claude-session-delete-${a.id}`,"aria-label":`Delete session ${a.id}`,children:e.jsx(W,{size:14,"aria-hidden":!0})})]})]}),m&&e.jsxs(h,{gap:1,style:{marginTop:"var(--space-2)"},children:[e.jsx(c,{variant:"danger",onClick:()=>void y(),"data-testid":`claude-session-confirm-delete-${a.id}`,children:"Confirm delete"}),e.jsx(c,{variant:"ghost",onClick:()=>n(!1),"data-testid":`claude-session-cancel-delete-${a.id}`,children:"Cancel"})]})]})}function G({onCreated:a,onCancel:p}){const[i,u]=r.useState(""),[l,o]=r.useState("general"),[d,m]=r.useState(""),[n,v]=r.useState(""),[f,g]=r.useState(!1),[x,y]=r.useState(null),t=async()=>{if(!(!l.trim()||!d.trim()||f)){g(!0),y(null);try{const s=await S("/api/claude-sessions/new",{method:"POST",body:{title:i.trim()||null,agent:l.trim(),prompt:d.trim(),directory:n.trim()||void 0}});a(s.id)}catch(s){y((s instanceof C,s.message))}finally{g(!1)}}};return e.jsxs(j,{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:"Title (optional)"}),e.jsx(b,{value:i,"data-testid":"claude-sessions-new-title",onChange:s=>u(s.target.value)})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Agent"}),e.jsx(b,{value:l,"data-testid":"claude-sessions-new-agent",onChange:s=>o(s.target.value)})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Seed prompt"}),e.jsx("textarea",{value:d,rows:4,"data-testid":"claude-sessions-new-prompt",onChange:s=>m(s.target.value),style:{background:"var(--surface-0)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"var(--space-2)",color:"var(--fg)",fontFamily:"var(--font-sans)",fontSize:"var(--fs-13)",resize:"vertical"}})]}),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:"Working directory (optional)"}),e.jsx(b,{value:n,"data-testid":"claude-sessions-new-directory",onChange:s=>v(s.target.value)})]}),x!==null&&e.jsx("span",{role:"alert","data-testid":"claude-sessions-new-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:x}),e.jsxs(h,{justify:"end",gap:2,children:[e.jsx(A,{asChild:!0,children:e.jsx(c,{variant:"ghost",onClick:p,"data-testid":"claude-sessions-new-cancel",children:"Cancel"})}),e.jsx(c,{variant:"primary",onClick:()=>void t(),disabled:f||!l.trim()||!d.trim(),"data-testid":"claude-sessions-new-submit",children:"Create"})]})]})}export{ce as ClaudeSessionsView};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeSessionsView-BoZS5ldi.js","sources":["../../src/web/v8/views/ClaudeSessions/ClaudeSessionDetail.tsx","../../src/web/v8/views/ClaudeSessions/ClaudeSessionsView.tsx"],"sourcesContent":["/**\n * v8/views/ClaudeSessions/ClaudeSessionDetail.tsx — Sprint S39, v9.3.0.\n *\n * Right-pane content for the ClaudeSessionSheet. Pulls messages\n * from /api/claude-sessions/:id/messages, lets the user send a\n * follow-up via /api/claude-sessions/:id/send. No streaming in\n * this initial cut — the server's SSE endpoint\n * (/api/claude-sessions/:id/stream) is read by the SDK in\n * production, but for the dashboard we treat send as fire-and-\n * refresh so the user sees the new turn after the resume exits.\n */\n\nimport { useCallback, useState } from 'react';\nimport { Send, RefreshCcw, MessageSquare } 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 { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { ErrorState } from '../../ui/feedback/ErrorState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { ChatMessage } from '../../data/types.js';\nimport { MessageBubble } from '../../ui/chat/MessageBubble.js';\n\ninterface MessagesPayload {\n messages: ChatMessage[];\n}\n\nexport function ClaudeSessionDetail({ sessionId }: { sessionId: string }): JSX.Element {\n const url = `/api/claude-sessions/${sessionId}/messages`;\n const payload = useFetch<MessagesPayload>(url);\n const [draft, setDraft] = useState<string>('');\n const [agent, setAgent] = useState<string>('general');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n const messages = payload.data?.messages ?? [];\n\n const send = async (): Promise<void> => {\n const text = draft.trim();\n if (!text || !agent.trim() || busy) return;\n setBusy(true);\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${sessionId}/send`, {\n method: 'POST',\n body: { message: text, agent: agent.trim() },\n });\n setDraft('');\n // The resume spawn is asynchronous; give it a moment then refresh.\n window.setTimeout(() => { refresh(); }, 750);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }} data-testid={`claude-session-detail-${sessionId}`}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>{sessionId}</strong>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid={`claude-session-detail-refresh-${sessionId}`}>\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n\n <Card variant=\"default\">\n <CardBody>\n {payload.error != null ? (\n <ErrorState\n error={payload.error}\n onRetry={refresh}\n description=\"Failed to load session messages.\"\n />\n ) : payload.loading && messages.length === 0 ? (\n <Skeleton style={{ height: 120 }} />\n ) : messages.length === 0 ? (\n <EmptyState\n icon={<MessageSquare size={28} aria-hidden />}\n title=\"No messages yet\"\n description=\"Send a follow-up below to start the conversation.\"\n data-testid={`claude-session-detail-empty-${sessionId}`}\n />\n ) : (\n <Stack gap={1}>\n {messages.map((m) => (\n <MessageBubble key={m.id || `${m.ts}-${m.role}`} message={m} />\n ))}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n {error !== null && (\n <span role=\"alert\" data-testid={`claude-session-detail-error-${sessionId}`} style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Agent</span>\n <Input\n value={agent}\n data-testid={`claude-session-detail-agent-${sessionId}`}\n onChange={(e) => setAgent((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Follow-up</span>\n <textarea\n value={draft}\n rows={4}\n data-testid={`claude-session-detail-draft-${sessionId}`}\n onChange={(e) => setDraft((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-sans)',\n fontSize: 'var(--fs-13)',\n resize: 'vertical',\n }}\n />\n </label>\n <Inline justify=\"end\" gap={2}>\n <Button\n variant=\"primary\"\n onClick={() => void send()}\n disabled={busy || draft.trim() === '' || agent.trim() === ''}\n data-testid={`claude-session-detail-send-${sessionId}`}\n >\n <Send size={14} aria-hidden /> {busy ? 'Sending…' : 'Send'}\n </Button>\n </Inline>\n </Stack>\n );\n}","/**\n * v8/views/ClaudeSessions/ClaudeSessionsView.tsx — Sprint S39, v9.3.0.\n *\n * Claude Code session explorer. Lists sessions on disk (via\n * /api/claude-sessions), lets the user create a new one via Sheet\n * (POST /api/claude-sessions/new), inline-rename (PATCH\n * /api/claude-sessions/:id), inline-confirm delete (DELETE\n * /api/claude-sessions/:id), and opens a right Drawer with the\n * session detail (ClaudeSessionDetail).\n */\n\nimport { useCallback, useState } from 'react';\nimport { Plus, Trash2, Pencil, RefreshCcw, MessageSquareText } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { ClaudeSession } from '../../data/types.js';\nimport { ClaudeSessionDetail } from './ClaudeSessionDetail.js';\n\ninterface SessionsPayload {\n sessions: ClaudeSession[];\n}\n\nexport function ClaudeSessionsView(): JSX.Element {\n const payload = useFetch<SessionsPayload>('/api/claude-sessions');\n const [creating, setCreating] = useState<boolean>(false);\n const [detailId, setDetailId] = useState<string | null>(null);\n\n const sessions = payload.data?.sessions ?? [];\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n return (\n <Stack gap={4} data-testid=\"claude-sessions-view\">\n <ViewHeader\n title=\"Claude sessions\"\n description=\"Claude Code session explorer. Each row is a session directory under ~/.claude/sessions/.\"\n actions={\n <Inline align=\"center\" gap={2}>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"claude-sessions-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setCreating(true)} data-testid=\"claude-sessions-new\">\n <Plus size={14} aria-hidden /> New session\n </Button>\n </Inline>\n }\n />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && sessions.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 36 }} />\n <Skeleton style={{ height: 36 }} />\n </Stack>\n ) : sessions.length === 0 ? (\n <EmptyState\n icon={<MessageSquareText size={28} aria-hidden />}\n title=\"No Claude sessions\"\n description=\"Create one to start a multi-turn conversation with Claude Code.\"\n />\n ) : (\n <Stack gap={2}>\n {sessions.map((s) => (\n <SessionRow key={s.id} session={s} onRefresh={refresh} onOpen={setDetailId} />\n ))}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={creating} onOpenChange={setCreating}>\n <SheetContent side=\"right\" title=\"New Claude session\" description=\"Spawn a Claude Code session via the runner.\">\n <NewSessionForm\n onCreated={(id) => {\n setCreating(false);\n refresh();\n setDetailId(id);\n }}\n onCancel={() => setCreating(false)}\n />\n </SheetContent>\n </Sheet>\n\n <Sheet open={detailId !== null} onOpenChange={(open) => { if (!open) setDetailId(null); }}>\n <SheetContent side=\"right\" title=\"Session detail\" description={detailId ?? ''}>\n {detailId !== null && <ClaudeSessionDetail sessionId={detailId} />}\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction SessionRow({\n session,\n onRefresh,\n onOpen,\n}: {\n session: ClaudeSession;\n onRefresh: () => void;\n onOpen: (id: string) => void;\n}): JSX.Element {\n const [renaming, setRenaming] = useState<boolean>(false);\n const [title, setTitle] = useState<string>(session.title ?? '');\n const [confirmDelete, setConfirmDelete] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const rename = async (): Promise<void> => {\n if (!title.trim()) return;\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${session.id}`, {\n method: 'PATCH',\n body: { title: title.trim() },\n });\n setRenaming(false);\n onRefresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const resume = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${id}/resume`, { method: 'POST', body: {} });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const remove = async (): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/claude-sessions/${session.id}`, { method: 'DELETE' });\n setConfirmDelete(false);\n onRefresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <div\n data-testid={`claude-session-row-${session.id}`}\n style={{\n padding: 'var(--space-3)',\n borderRadius: 'var(--radius-md)',\n border: '1px solid var(--border)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ minWidth: 0, flex: 1 }}>\n {renaming ? (\n <Inline gap={1}>\n <Input\n value={title}\n data-testid={`claude-session-rename-input-${session.id}`}\n onChange={(e) => setTitle((e.target as HTMLInputElement).value)}\n />\n <Button variant=\"primary\" onClick={() => void rename()} data-testid={`claude-session-rename-submit-${session.id}`}>Save</Button>\n <Button variant=\"ghost\" onClick={() => { setRenaming(false); setTitle(session.title ?? ''); }}>Cancel</Button>\n </Inline>\n ) : (\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>{session.title || session.id}</strong>\n {session.agent && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>\n @{session.agent}\n </span>\n )}\n </Inline>\n )}\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {session.id}\n </span>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button variant=\"primary\" onClick={() => void resume(session.id)} data-testid={`claude-session-resume-${session.id}`} aria-label={`Resume ${session.id}`}>\n Resume\n </Button>\n <Button variant=\"ghost\" onClick={() => onOpen(session.id)} data-testid={`claude-session-open-${session.id}`}>\n Open\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => { setRenaming(true); setTitle(session.title ?? ''); }}\n data-testid={`claude-session-rename-${session.id}`}\n aria-label={`Rename session ${session.id}`}\n >\n <Pencil size={14} aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => !cur)}\n data-testid={`claude-session-delete-${session.id}`}\n aria-label={`Delete session ${session.id}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {confirmDelete && (\n <Inline gap={1} style={{ marginTop: 'var(--space-2)' }}>\n <Button variant=\"danger\" onClick={() => void remove()} data-testid={`claude-session-confirm-delete-${session.id}`}>\n Confirm delete\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(false)} data-testid={`claude-session-cancel-delete-${session.id}`}>\n Cancel\n </Button>\n </Inline>\n )}\n </div>\n );\n}\n\nfunction NewSessionForm({\n onCreated,\n onCancel,\n}: {\n onCreated: (id: string) => void;\n onCancel: () => void;\n}): JSX.Element {\n const [title, setTitle] = useState<string>('');\n const [agent, setAgent] = useState<string>('general');\n const [prompt, setPrompt] = useState<string>('');\n const [directory, setDirectory] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (): Promise<void> => {\n if (!agent.trim() || !prompt.trim() || busy) return;\n setBusy(true);\n setError(null);\n try {\n const res = await fetchJson<{ id: string }>('/api/claude-sessions/new', {\n method: 'POST',\n body: {\n title: title.trim() || null,\n agent: agent.trim(),\n prompt: prompt.trim(),\n directory: directory.trim() || undefined,\n },\n });\n onCreated(res.id);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Title (optional)</span>\n <Input\n value={title}\n data-testid=\"claude-sessions-new-title\"\n onChange={(e) => setTitle((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Agent</span>\n <Input\n value={agent}\n data-testid=\"claude-sessions-new-agent\"\n onChange={(e) => setAgent((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Seed prompt</span>\n <textarea\n value={prompt}\n rows={4}\n data-testid=\"claude-sessions-new-prompt\"\n onChange={(e) => setPrompt((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-sans)',\n fontSize: 'var(--fs-13)',\n resize: 'vertical',\n }}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Working directory (optional)</span>\n <Input\n value={directory}\n data-testid=\"claude-sessions-new-directory\"\n onChange={(e) => setDirectory((e.target as HTMLInputElement).value)}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" data-testid=\"claude-sessions-new-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel} data-testid=\"claude-sessions-new-cancel\">Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={() => void submit()}\n disabled={busy || !agent.trim() || !prompt.trim()}\n data-testid=\"claude-sessions-new-submit\"\n >\n Create\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["ClaudeSessionDetail","sessionId","url","payload","useFetch","draft","setDraft","useState","agent","setAgent","busy","setBusy","error","setError","refresh","useCallback","messages","_a","send","text","fetchJson","err","FetchError","jsxs","Stack","Inline","jsx","Button","RefreshCcw","Card","CardBody","ErrorState","Skeleton","EmptyState","MessageSquare","m","MessageBubble","Input","e","Send","ClaudeSessionsView","creating","setCreating","detailId","setDetailId","sessions","ViewHeader","Plus","MessageSquareText","s","SessionRow","Sheet","SheetContent","NewSessionForm","id","open","session","onRefresh","onOpen","renaming","setRenaming","title","setTitle","confirmDelete","setConfirmDelete","rename","resume","remove","Pencil","cur","Trash2","onCreated","onCancel","prompt","setPrompt","directory","setDirectory","submit","res","SheetClose"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r,j as e}from"./cmdk-C3F6LD6N.js";import{u as z,S as h,I as f,B as n,h as y,a1 as w,i as b,F as k}from"./main-BRmJZcHt.js";import{V as E}from"./ViewHeader-BsnaspKw.js";import{C as T,b as D}from"./Card-Clkvh43Q.js";import{I as S}from"./Input-DV-vdaV8.js";import{T as C}from"./Textarea-BfXGMXQ7.js";import{S as R,a as $}from"./Sheet-BwMVGN-8.js";import{E as L}from"./EmptyState-ccT__JZG.js";import{R as B}from"./refresh-ccw-DN_zCB1h.js";import{P as F}from"./plus-Cps-8lcG.js";import{E as I}from"./external-link-DPDQM1YO.js";import{T as P}from"./trash-2-B_Y6HrfN.js";function Q(){const l=z("/api/clipboard/list"),[v,s]=r.useState(!1),[x,o]=r.useState(null),[u,d]=r.useState(null),p=r.useMemo(()=>{var t;return((t=l.data)==null?void 0:t.clips)??[]},[l.data]),c=r.useCallback(()=>{l.refetch()},[l]),g=async t=>{d(null);try{await b(`/api/clipboard/${t}`,{method:"DELETE"}),o(null),c()}catch(i){d((i instanceof k,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(B,{size:14,"aria-hidden":!0})," Refresh"]}),e.jsxs(n,{variant:"primary",onClick:()=>s(!0),"data-testid":"clipboard-add",children:[e.jsx(F,{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:"Clips are saved URL + text pairs captured from the clipboard during agent work. Each becomes a markdown note under clips/. Save one to get started."}):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(I,{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(P,{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:s,children:e.jsx($,{side:"right",title:"Save clip",description:"URL or content required.",children:e.jsx(U,{onSubmit:async t=>{await b("/api/clipboard/save",{method:"POST",body:t}),s(!1),c()},onCancel:()=>s(!1)})})})]})}function U({onSubmit:l,onCancel:v}){const[s,x]=r.useState(""),[o,u]=r.useState(""),[d,p]=r.useState(""),[c,g]=r.useState(""),[t,i]=r.useState(!1),[m,j]=r.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(S,{value:s,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(S,{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||!s.trim()&&!d.trim(),"data-testid":"clipboard-form-submit",onClick:async()=>{i(!0),j(null);try{await l({url:s.trim()||void 0,title:o.trim()||void 0,content:d.trim()||void 0,selection:c.trim()||void 0})}catch(a){j((a instanceof k,a.message)),i(!1)}},children:t?"Saving…":"Save"})]})]})}export{Q as ClipboardView};
|
package/bizar-dash/dist/assets/{ClipboardView-CPlTU5VG.js.map → ClipboardView-Cb6XgYZI.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClipboardView-CPlTU5VG.js","sources":["../../src/web/v8/views/Clipboard/ClipboardView.tsx"],"sourcesContent":["/**\n * v8/views/Clipboard/ClipboardView.tsx — Sprint S43, v9.3.0.\n *\n * Saved clip list (GET /api/clipboard/list), Save Sheet\n * (POST /api/clipboard/save with {url, title, content, selection}),\n * inline-confirm Delete (DELETE /api/clipboard/:id). Each row links\n * to the source URL when present.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { ClipboardPaste, Plus, Trash2, ExternalLink, RefreshCcw } 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';\n\ninterface Clip {\n id: string;\n url?: string;\n title?: string;\n content?: string;\n selection?: string;\n savedAt?: string;\n}\n\nexport function ClipboardView(): JSX.Element {\n const payload = useFetch<{ clips: Clip[] }>('/api/clipboard/list');\n const [saving, setSaving] = useState<boolean>(false);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const clips = useMemo<Clip[]>(() => payload.data?.clips ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/clipboard/${id}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Stack gap={4} data-testid=\"clipboard-view\">\n <ViewHeader\n title=\"Clipboard\"\n description=\"Saved clips. Each becomes a markdown note under clips/.\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"clipboard-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"clipboard-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setSaving(true)} data-testid=\"clipboard-add\">\n <Plus size={14} aria-hidden /> Save clip\n </Button>\n </Inline>\n }\n />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && clips.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 60 }} />\n <Skeleton style={{ height: 60 }} />\n </Stack>\n ) : clips.length === 0 ? (\n <EmptyState icon={<ClipboardPaste size={28} aria-hidden />} title=\"No saved clips\" description=\"Clips are saved URL + text pairs captured from the clipboard during agent work. Each becomes a markdown note under clips/. Save one to get started.\" />\n ) : (\n <Stack gap={1}>\n {clips.map((c) => {\n const isConfirming = confirmDelete === c.id;\n return (\n <div\n key={c.id}\n data-testid={`clipboard-row-${c.id}`}\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 <strong style={{ fontSize: 'var(--fs-13)' }}>{c.title || c.id}</strong>\n {c.url && (\n <a href={c.url} target=\"_blank\" rel=\"noreferrer\" style={{ fontSize: 'var(--fs-11)', color: 'var(--accent)' }}>\n <ExternalLink size={10} aria-hidden style={{ verticalAlign: 'middle' }} /> {c.url}\n </a>\n )}\n {c.savedAt && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{c.savedAt}</span>}\n </Inline>\n {(c.selection || c.content) && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {(c.selection || c.content || '').length > 200\n ? `${(c.selection || c.content || '').slice(0, 200)}…`\n : (c.selection || c.content)}\n </span>\n )}\n </Stack>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === c.id ? null : c.id))} data-testid={`clipboard-delete-${c.id}`} aria-label={`Delete ${c.id}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(c.id)} data-testid={`clipboard-confirm-delete-${c.id}`}>\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={saving} onOpenChange={setSaving}>\n <SheetContent side=\"right\" title=\"Save clip\" description=\"URL or content required.\">\n <SaveForm\n onSubmit={async (body) => {\n await fetchJson('/api/clipboard/save', { method: 'POST', body });\n setSaving(false);\n refresh();\n }}\n onCancel={() => setSaving(false)}\n />\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction SaveForm({\n onSubmit,\n onCancel,\n}: {\n onSubmit: (body: { url?: string; title?: string; content?: string; selection?: string }) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [url, setUrl] = useState<string>('');\n const [title, setTitle] = useState<string>('');\n const [content, setContent] = useState<string>('');\n const [selection, setSelection] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>URL (optional)</span>\n <Input value={url} onChange={(e) => setUrl((e.target as HTMLInputElement).value)} data-testid=\"clipboard-form-url\" />\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 (optional)</span>\n <Input value={title} onChange={(e) => setTitle((e.target as HTMLInputElement).value)} data-testid=\"clipboard-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)' }}>Content</span>\n <Textarea value={content} rows={6} onChange={(e) => setContent((e.target as HTMLTextAreaElement).value)} data-testid=\"clipboard-form-content\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Selection (optional)</span>\n <Textarea value={selection} rows={3} onChange={(e) => setSelection((e.target as HTMLTextAreaElement).value)} data-testid=\"clipboard-form-selection\" />\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 || (!url.trim() && !content.trim())}\n data-testid=\"clipboard-form-submit\"\n onClick={async () => {\n setBusy(true);\n setError(null);\n try {\n await onSubmit({\n url: url.trim() || undefined,\n title: title.trim() || undefined,\n content: content.trim() || undefined,\n selection: selection.trim() || undefined,\n });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n setBusy(false);\n }\n }}\n >\n {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["ClipboardView","payload","useFetch","saving","setSaving","useState","confirmDelete","setConfirmDelete","error","setError","clips","useMemo","_a","refresh","useCallback","drop","id","fetchJson","err","FetchError","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCcw","Plus","Card","CardBody","Skeleton","EmptyState","ClipboardPaste","c","isConfirming","ExternalLink","cur","Trash2","Sheet","SheetContent","SaveForm","body","onSubmit","onCancel","url","setUrl","title","setTitle","content","setContent","selection","setSelection","busy","setBusy","Input","e","Textarea"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ClipboardView-Cb6XgYZI.js","sources":["../../src/web/v8/views/Clipboard/ClipboardView.tsx"],"sourcesContent":["/**\n * v8/views/Clipboard/ClipboardView.tsx — Sprint S43, v9.3.0.\n *\n * Saved clip list (GET /api/clipboard/list), Save Sheet\n * (POST /api/clipboard/save with {url, title, content, selection}),\n * inline-confirm Delete (DELETE /api/clipboard/:id). Each row links\n * to the source URL when present.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { ClipboardPaste, Plus, Trash2, ExternalLink, RefreshCcw } 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';\n\ninterface Clip {\n id: string;\n url?: string;\n title?: string;\n content?: string;\n selection?: string;\n savedAt?: string;\n}\n\nexport function ClipboardView(): JSX.Element {\n const payload = useFetch<{ clips: Clip[] }>('/api/clipboard/list');\n const [saving, setSaving] = useState<boolean>(false);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const clips = useMemo<Clip[]>(() => payload.data?.clips ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/clipboard/${id}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Stack gap={4} data-testid=\"clipboard-view\">\n <ViewHeader\n title=\"Clipboard\"\n description=\"Saved clips. Each becomes a markdown note under clips/.\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"clipboard-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"clipboard-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setSaving(true)} data-testid=\"clipboard-add\">\n <Plus size={14} aria-hidden /> Save clip\n </Button>\n </Inline>\n }\n />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && clips.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 60 }} />\n <Skeleton style={{ height: 60 }} />\n </Stack>\n ) : clips.length === 0 ? (\n <EmptyState icon={<ClipboardPaste size={28} aria-hidden />} title=\"No saved clips\" description=\"Clips are saved URL + text pairs captured from the clipboard during agent work. Each becomes a markdown note under clips/. Save one to get started.\" />\n ) : (\n <Stack gap={1}>\n {clips.map((c) => {\n const isConfirming = confirmDelete === c.id;\n return (\n <div\n key={c.id}\n data-testid={`clipboard-row-${c.id}`}\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 <strong style={{ fontSize: 'var(--fs-13)' }}>{c.title || c.id}</strong>\n {c.url && (\n <a href={c.url} target=\"_blank\" rel=\"noreferrer\" style={{ fontSize: 'var(--fs-11)', color: 'var(--accent)' }}>\n <ExternalLink size={10} aria-hidden style={{ verticalAlign: 'middle' }} /> {c.url}\n </a>\n )}\n {c.savedAt && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{c.savedAt}</span>}\n </Inline>\n {(c.selection || c.content) && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {(c.selection || c.content || '').length > 200\n ? `${(c.selection || c.content || '').slice(0, 200)}…`\n : (c.selection || c.content)}\n </span>\n )}\n </Stack>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === c.id ? null : c.id))} data-testid={`clipboard-delete-${c.id}`} aria-label={`Delete ${c.id}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(c.id)} data-testid={`clipboard-confirm-delete-${c.id}`}>\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={saving} onOpenChange={setSaving}>\n <SheetContent side=\"right\" title=\"Save clip\" description=\"URL or content required.\">\n <SaveForm\n onSubmit={async (body) => {\n await fetchJson('/api/clipboard/save', { method: 'POST', body });\n setSaving(false);\n refresh();\n }}\n onCancel={() => setSaving(false)}\n />\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction SaveForm({\n onSubmit,\n onCancel,\n}: {\n onSubmit: (body: { url?: string; title?: string; content?: string; selection?: string }) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [url, setUrl] = useState<string>('');\n const [title, setTitle] = useState<string>('');\n const [content, setContent] = useState<string>('');\n const [selection, setSelection] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>URL (optional)</span>\n <Input value={url} onChange={(e) => setUrl((e.target as HTMLInputElement).value)} data-testid=\"clipboard-form-url\" />\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 (optional)</span>\n <Input value={title} onChange={(e) => setTitle((e.target as HTMLInputElement).value)} data-testid=\"clipboard-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)' }}>Content</span>\n <Textarea value={content} rows={6} onChange={(e) => setContent((e.target as HTMLTextAreaElement).value)} data-testid=\"clipboard-form-content\" />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Selection (optional)</span>\n <Textarea value={selection} rows={3} onChange={(e) => setSelection((e.target as HTMLTextAreaElement).value)} data-testid=\"clipboard-form-selection\" />\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 || (!url.trim() && !content.trim())}\n data-testid=\"clipboard-form-submit\"\n onClick={async () => {\n setBusy(true);\n setError(null);\n try {\n await onSubmit({\n url: url.trim() || undefined,\n title: title.trim() || undefined,\n content: content.trim() || undefined,\n selection: selection.trim() || undefined,\n });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n setBusy(false);\n }\n }}\n >\n {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["ClipboardView","payload","useFetch","saving","setSaving","useState","confirmDelete","setConfirmDelete","error","setError","clips","useMemo","_a","refresh","useCallback","drop","id","fetchJson","err","FetchError","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCcw","Plus","Card","CardBody","Skeleton","EmptyState","ClipboardPaste","c","isConfirming","ExternalLink","cur","Trash2","Sheet","SheetContent","SaveForm","body","onSubmit","onCancel","url","setUrl","title","setTitle","content","setContent","selection","setSelection","busy","setBusy","Input","e","Textarea"],"mappings":"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"}
|