@polderlabs/bizar 10.0.7 → 10.2.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/README.md +0 -2
- package/bizar-dash/dist/assets/{ActivityFeed-Da-JCrE6.js → ActivityFeed-JjmOY2AQ.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityFeed-Da-JCrE6.js.map → ActivityFeed-JjmOY2AQ.js.map} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-nIRsSETb.js → ActivityView-BIIMvGWo.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-nIRsSETb.js.map → ActivityView-BIIMvGWo.js.map} +1 -1
- package/bizar-dash/dist/assets/{AdminView-DP1NMxmG.js → AdminView-DRidJtkq.js} +1 -1
- package/bizar-dash/dist/assets/{AdminView-DP1NMxmG.js.map → AdminView-DRidJtkq.js.map} +1 -1
- package/bizar-dash/dist/assets/{AgentActivity-lSPkOr-O.js → AgentActivity-79l4SBMC.js} +1 -1
- package/bizar-dash/dist/assets/{AgentActivity-lSPkOr-O.js.map → AgentActivity-79l4SBMC.js.map} +1 -1
- package/bizar-dash/dist/assets/{AgentsView-BIWGkz7w.js → AgentsView-0vT4uPSc.js} +1 -1
- package/bizar-dash/dist/assets/{AgentsView-BIWGkz7w.js.map → AgentsView-0vT4uPSc.js.map} +1 -1
- package/bizar-dash/dist/assets/{Alert-DN0UysMg.js → Alert-CG5q_s75.js} +1 -1
- package/bizar-dash/dist/assets/{Alert-DN0UysMg.js.map → Alert-CG5q_s75.js.map} +1 -1
- package/bizar-dash/dist/assets/ArtifactsView-DM8ZmpR9.js +21 -0
- package/bizar-dash/dist/assets/ArtifactsView-DM8ZmpR9.js.map +1 -0
- package/bizar-dash/dist/assets/{AuthView-DW5cs7ma.js → AuthView-BveN94MC.js} +1 -1
- package/bizar-dash/dist/assets/{AuthView-DW5cs7ma.js.map → AuthView-BveN94MC.js.map} +1 -1
- package/bizar-dash/dist/assets/{Avatar-DZPv9pvd.js → Avatar-ulUPIYTd.js} +1 -1
- package/bizar-dash/dist/assets/{Avatar-DZPv9pvd.js.map → Avatar-ulUPIYTd.js.map} +1 -1
- package/bizar-dash/dist/assets/{BackgroundJobsView-D8O-EyMD.js → BackgroundJobsView-BWErhqFo.js} +1 -1
- package/bizar-dash/dist/assets/{BackgroundJobsView-D8O-EyMD.js.map → BackgroundJobsView-BWErhqFo.js.map} +1 -1
- package/bizar-dash/dist/assets/{BackupView-uwXkhxOV.js → BackupView-CnBjzG9N.js} +1 -1
- package/bizar-dash/dist/assets/{BackupView-uwXkhxOV.js.map → BackupView-CnBjzG9N.js.map} +1 -1
- package/bizar-dash/dist/assets/{Card-Tyboihu7.js → Card-B0imhxMk.js} +1 -1
- package/bizar-dash/dist/assets/{Card-Tyboihu7.js.map → Card-B0imhxMk.js.map} +1 -1
- package/bizar-dash/dist/assets/{ChatView-DRBHzgay.js → ChatView-D6zGytzx.js} +1 -1
- package/bizar-dash/dist/assets/{ChatView-DRBHzgay.js.map → ChatView-D6zGytzx.js.map} +1 -1
- package/bizar-dash/dist/assets/{Chip-BrXIlR9w.js → Chip-wwZSGwLE.js} +1 -1
- package/bizar-dash/dist/assets/{Chip-BrXIlR9w.js.map → Chip-wwZSGwLE.js.map} +1 -1
- package/bizar-dash/dist/assets/{ClaudeSessionsView-Ck62jaOr.js → ClaudeSessionsView-DK1sOLhi.js} +1 -1
- package/bizar-dash/dist/assets/{ClaudeSessionsView-Ck62jaOr.js.map → ClaudeSessionsView-DK1sOLhi.js.map} +1 -1
- package/bizar-dash/dist/assets/{ClipboardView-DfND6xL6.js → ClipboardView-CZ2lYPr0.js} +1 -1
- package/bizar-dash/dist/assets/{ClipboardView-DfND6xL6.js.map → ClipboardView-CZ2lYPr0.js.map} +1 -1
- package/bizar-dash/dist/assets/{ConfigView-DjJmSrOJ.js → ConfigView-D-zT9eNA.js} +1 -1
- package/bizar-dash/dist/assets/{ConfigView-DjJmSrOJ.js.map → ConfigView-D-zT9eNA.js.map} +1 -1
- package/bizar-dash/dist/assets/{DiagnosticsView-CKgItf0J.js → DiagnosticsView-BocV68Lb.js} +1 -1
- package/bizar-dash/dist/assets/{DiagnosticsView-CKgItf0J.js.map → DiagnosticsView-BocV68Lb.js.map} +1 -1
- package/bizar-dash/dist/assets/{DialogsView-DHYF8dE1.js → DialogsView-BVjPI5x7.js} +1 -1
- package/bizar-dash/dist/assets/{DialogsView-DHYF8dE1.js.map → DialogsView-BVjPI5x7.js.map} +1 -1
- package/bizar-dash/dist/assets/{DoctorView-DDLHrSKk.js → DoctorView-84gJcZwM.js} +1 -1
- package/bizar-dash/dist/assets/{DoctorView-DDLHrSKk.js.map → DoctorView-84gJcZwM.js.map} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-DZ2ouKwd.js → EmptyState-BjgVOrcO.js} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-DZ2ouKwd.js.map → EmptyState-BjgVOrcO.js.map} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsView-D1cx83mB.js → EnvVarsView-BJ2TEzF7.js} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsView-D1cx83mB.js.map → EnvVarsView-BJ2TEzF7.js.map} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-DwwJ2-Jq.js → ErrorState-BE3WBFqF.js} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-DwwJ2-Jq.js.map → ErrorState-BE3WBFqF.js.map} +1 -1
- package/bizar-dash/dist/assets/{EvalView-C9aYixXW.js → EvalView-BJJ2P-kK.js} +1 -1
- package/bizar-dash/dist/assets/{EvalView-C9aYixXW.js.map → EvalView-BJJ2P-kK.js.map} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-DZa_mGmh.js → GoalsView-pwROHApi.js} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-DZa_mGmh.js.map → GoalsView-pwROHApi.js.map} +1 -1
- package/bizar-dash/dist/assets/{Grid-CiRyhAgR.js → Grid-qcvbhx6e.js} +1 -1
- package/bizar-dash/dist/assets/{Grid-CiRyhAgR.js.map → Grid-qcvbhx6e.js.map} +1 -1
- package/bizar-dash/dist/assets/{HeadroomView-CNc-TI7u.js → HeadroomView-D1UiTYbt.js} +1 -1
- package/bizar-dash/dist/assets/{HeadroomView-CNc-TI7u.js.map → HeadroomView-D1UiTYbt.js.map} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-Dv7aPxJE.js → HistoryView-C7SSOLJA.js} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-Dv7aPxJE.js.map → HistoryView-C7SSOLJA.js.map} +1 -1
- package/bizar-dash/dist/assets/{Input-BbFUDQnS.js → Input-Bgzxf_Hu.js} +1 -1
- package/bizar-dash/dist/assets/{Input-BbFUDQnS.js.map → Input-Bgzxf_Hu.js.map} +1 -1
- package/bizar-dash/dist/assets/{LibrariesView-DBQ83TNa.js → LibrariesView-CbFFksox.js} +1 -1
- package/bizar-dash/dist/assets/{LibrariesView-DBQ83TNa.js.map → LibrariesView-CbFFksox.js.map} +1 -1
- package/bizar-dash/dist/assets/{LightRAGView-JYpE5u9p.js → LightRAGView-BqDrJbRq.js} +1 -1
- package/bizar-dash/dist/assets/{LightRAGView-JYpE5u9p.js.map → LightRAGView-BqDrJbRq.js.map} +1 -1
- package/bizar-dash/dist/assets/{ListHeader-BGjm11Z0.js → ListHeader-TjPJrUfY.js} +1 -1
- package/bizar-dash/dist/assets/{ListHeader-BGjm11Z0.js.map → ListHeader-TjPJrUfY.js.map} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-CnOP2MvM.js → MemoryView-BlTeHLhX.js} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-CnOP2MvM.js.map → MemoryView-BlTeHLhX.js.map} +1 -1
- package/bizar-dash/dist/assets/{MiscView-BBcpUbZZ.js → MiscView-B8QY82Pm.js} +1 -1
- package/bizar-dash/dist/assets/{MiscView-BBcpUbZZ.js.map → MiscView-B8QY82Pm.js.map} +1 -1
- package/bizar-dash/dist/assets/{ModsView-CU4cAmIz.js → ModsView-CvW1OWts.js} +1 -1
- package/bizar-dash/dist/assets/{ModsView-CU4cAmIz.js.map → ModsView-CvW1OWts.js.map} +1 -1
- package/bizar-dash/dist/assets/{NotificationsView-BYffvthq.js → NotificationsView-CsBt5U7x.js} +1 -1
- package/bizar-dash/dist/assets/{NotificationsView-BYffvthq.js.map → NotificationsView-CsBt5U7x.js.map} +1 -1
- package/bizar-dash/dist/assets/{ObsidianView-D3bI0row.js → ObsidianView-BCTejEj2.js} +1 -1
- package/bizar-dash/dist/assets/{ObsidianView-D3bI0row.js.map → ObsidianView-BCTejEj2.js.map} +1 -1
- package/bizar-dash/dist/assets/{OverviewView-0tq8f-Y0.js → OverviewView-BsuPxwnB.js} +1 -1
- package/bizar-dash/dist/assets/{OverviewView-0tq8f-Y0.js.map → OverviewView-BsuPxwnB.js.map} +1 -1
- package/bizar-dash/dist/assets/{ProgressBar-B-h60LKA.js → ProgressBar-DlZTETEn.js} +1 -1
- package/bizar-dash/dist/assets/{ProgressBar-B-h60LKA.js.map → ProgressBar-DlZTETEn.js.map} +1 -1
- package/bizar-dash/dist/assets/{ProjectsView-DhX5lzHS.js → ProjectsView-Soxtmpet.js} +1 -1
- package/bizar-dash/dist/assets/{ProjectsView-DhX5lzHS.js.map → ProjectsView-Soxtmpet.js.map} +1 -1
- package/bizar-dash/dist/assets/{ProvidersView-CJMX7jm9.js → ProvidersView-DaCEV9pM.js} +1 -1
- package/bizar-dash/dist/assets/{ProvidersView-CJMX7jm9.js.map → ProvidersView-DaCEV9pM.js.map} +1 -1
- package/bizar-dash/dist/assets/{SchedulesView-CcwDQ9Nm.js → SchedulesView-DY2ByBj_.js} +1 -1
- package/bizar-dash/dist/assets/{SchedulesView-CcwDQ9Nm.js.map → SchedulesView-DY2ByBj_.js.map} +1 -1
- package/bizar-dash/dist/assets/{Select-Cw7Qtz2M.js → Select-Dbd88_n8.js} +1 -1
- package/bizar-dash/dist/assets/{Select-Cw7Qtz2M.js.map → Select-Dbd88_n8.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-DgsgbPSI.js → SettingsRow-CLMNd434.js} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-DgsgbPSI.js.map → SettingsRow-CLMNd434.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsView-DTAFdKyK.js → SettingsView-b24oFq9x.js} +1 -1
- package/bizar-dash/dist/assets/{SettingsView-DTAFdKyK.js.map → SettingsView-b24oFq9x.js.map} +1 -1
- package/bizar-dash/dist/assets/{Sheet-DH-WNJ3Y.js → Sheet-DnDid58j.js} +1 -1
- package/bizar-dash/dist/assets/{Sheet-DH-WNJ3Y.js.map → Sheet-DnDid58j.js.map} +1 -1
- package/bizar-dash/dist/assets/{Slider-DXbJuQ7y.js → Slider-BJCvKI1I.js} +1 -1
- package/bizar-dash/dist/assets/{Slider-DXbJuQ7y.js.map → Slider-BJCvKI1I.js.map} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-CYtAn82j.js → Sparkline-ktqQLdyb.js} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-CYtAn82j.js.map → Sparkline-ktqQLdyb.js.map} +1 -1
- package/bizar-dash/dist/assets/{Switch-BItGrPqr.js → Switch-CwXfsDii.js} +1 -1
- package/bizar-dash/dist/assets/{Switch-BItGrPqr.js.map → Switch-CwXfsDii.js.map} +1 -1
- package/bizar-dash/dist/assets/{TasksView-i5tm6CkX.js → TasksView-BHmpzFCf.js} +1 -1
- package/bizar-dash/dist/assets/{TasksView-i5tm6CkX.js.map → TasksView-BHmpzFCf.js.map} +1 -1
- package/bizar-dash/dist/assets/{Textarea-qYDf3yds.js → Textarea-BzIAwSlp.js} +1 -1
- package/bizar-dash/dist/assets/{Textarea-qYDf3yds.js.map → Textarea-BzIAwSlp.js.map} +1 -1
- package/bizar-dash/dist/assets/{UpdateView-Xln-ej26.js → UpdateView-CSmX9NN0.js} +1 -1
- package/bizar-dash/dist/assets/{UpdateView-Xln-ej26.js.map → UpdateView-CSmX9NN0.js.map} +1 -1
- package/bizar-dash/dist/assets/{UsageView-BGuZSUZ6.js → UsageView-COyr_Gfi.js} +1 -1
- package/bizar-dash/dist/assets/{UsageView-BGuZSUZ6.js.map → UsageView-COyr_Gfi.js.map} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-BqIPVKuG.js → ViewHeader-BzYZ3m-e.js} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-BqIPVKuG.js.map → ViewHeader-BzYZ3m-e.js.map} +1 -1
- package/bizar-dash/dist/assets/{VoiceView-CWUOCQs_.js → VoiceView-D33_xG5t.js} +1 -1
- package/bizar-dash/dist/assets/{VoiceView-CWUOCQs_.js.map → VoiceView-D33_xG5t.js.map} +1 -1
- package/bizar-dash/dist/assets/{brain-fsBSDl2g.js → brain-CM-Vls8r.js} +1 -1
- package/bizar-dash/dist/assets/{brain-fsBSDl2g.js.map → brain-CM-Vls8r.js.map} +1 -1
- package/bizar-dash/dist/assets/{calendar-DsHTZoCU.js → calendar-C0lgZk69.js} +1 -1
- package/bizar-dash/dist/assets/{calendar-DsHTZoCU.js.map → calendar-C0lgZk69.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-CqSxqqeJ.js → circle-Bx_hQEBC.js} +1 -1
- package/bizar-dash/dist/assets/{circle-CqSxqqeJ.js.map → circle-Bx_hQEBC.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-BsLl001l.js → circle-alert-DHvsqpw5.js} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-BsLl001l.js.map → circle-alert-DHvsqpw5.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-check-rVKMQmZp.js → circle-check-Bx8wmXR9.js} +1 -1
- package/bizar-dash/dist/assets/{circle-check-rVKMQmZp.js.map → circle-check-Bx8wmXR9.js.map} +1 -1
- package/bizar-dash/dist/assets/{clock-OuficfgH.js → clock-CejGoecX.js} +1 -1
- package/bizar-dash/dist/assets/{clock-OuficfgH.js.map → clock-CejGoecX.js.map} +1 -1
- package/bizar-dash/dist/assets/{download-BdHlstUY.js → download-4cEUWue1.js} +1 -1
- package/bizar-dash/dist/assets/{download-BdHlstUY.js.map → download-4cEUWue1.js.map} +1 -1
- package/bizar-dash/dist/assets/{external-link-DA3_VGm-.js → external-link-0NqUhI4i.js} +1 -1
- package/bizar-dash/dist/assets/{external-link-DA3_VGm-.js.map → external-link-0NqUhI4i.js.map} +1 -1
- package/bizar-dash/dist/assets/{file-text-B-g8H227.js → file-text-yEMkrSoZ.js} +1 -1
- package/bizar-dash/dist/assets/{file-text-B-g8H227.js.map → file-text-yEMkrSoZ.js.map} +1 -1
- package/bizar-dash/dist/assets/{filter-D9B8s5CG.js → filter-BXt60zAS.js} +1 -1
- package/bizar-dash/dist/assets/{filter-D9B8s5CG.js.map → filter-BXt60zAS.js.map} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-ByH0YuVz.js → git-pull-request-BjG5lNtR.js} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-ByH0YuVz.js.map → git-pull-request-BjG5lNtR.js.map} +1 -1
- package/bizar-dash/dist/assets/{main-CdOm1Pj9.js → main-CokHAXWM.js} +2 -2
- package/bizar-dash/dist/assets/{main-CdOm1Pj9.js.map → main-CokHAXWM.js.map} +1 -1
- package/bizar-dash/dist/assets/{pause-C9hgd8wX.js → pause-CAmulU0F.js} +1 -1
- package/bizar-dash/dist/assets/{pause-C9hgd8wX.js.map → pause-CAmulU0F.js.map} +1 -1
- package/bizar-dash/dist/assets/{pencil-BanqaMw7.js → pencil-eq5IqBmU.js} +1 -1
- package/bizar-dash/dist/assets/{pencil-BanqaMw7.js.map → pencil-eq5IqBmU.js.map} +1 -1
- package/bizar-dash/dist/assets/{play-CawUZ02_.js → play-BoLrrcBA.js} +1 -1
- package/bizar-dash/dist/assets/{play-CawUZ02_.js.map → play-BoLrrcBA.js.map} +1 -1
- package/bizar-dash/dist/assets/{plug-Cmv0-T_e.js → plug-DBrVM9lK.js} +1 -1
- package/bizar-dash/dist/assets/{plug-Cmv0-T_e.js.map → plug-DBrVM9lK.js.map} +1 -1
- package/bizar-dash/dist/assets/{plus-M6LYiKX8.js → plus-DENm0hqV.js} +1 -1
- package/bizar-dash/dist/assets/{plus-M6LYiKX8.js.map → plus-DENm0hqV.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-DP5x_SRF.js → power-DLjXF7zE.js} +1 -1
- package/bizar-dash/dist/assets/{power-DP5x_SRF.js.map → power-DLjXF7zE.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-off-NOJRLAIs.js → power-off-D47cOnG_.js} +1 -1
- package/bizar-dash/dist/assets/{power-off-NOJRLAIs.js.map → power-off-D47cOnG_.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-CHMprsm5.js → refresh-ccw-DNrXX9gB.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-CHMprsm5.js.map → refresh-ccw-DNrXX9gB.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-1RBqDKgJ.js → refresh-cw-CoAHDpeS.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-1RBqDKgJ.js.map → refresh-cw-CoAHDpeS.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-DJRekBbi.js → rotate-ccw-ObX5awaG.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-DJRekBbi.js.map → rotate-ccw-ObX5awaG.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-DHooc0Tx.js → rotate-cw-xpPJw9LP.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-DHooc0Tx.js.map → rotate-cw-xpPJw9LP.js.map} +1 -1
- package/bizar-dash/dist/assets/{save-DQKCKyZK.js → save-D1iKiJJl.js} +1 -1
- package/bizar-dash/dist/assets/{save-DQKCKyZK.js.map → save-D1iKiJJl.js.map} +1 -1
- package/bizar-dash/dist/assets/{send-xgy3RAi7.js → send-BRcAhZUm.js} +1 -1
- package/bizar-dash/dist/assets/{send-xgy3RAi7.js.map → send-BRcAhZUm.js.map} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-CWV2F5ab.js → shield-alert-C6vEcK-g.js} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-CWV2F5ab.js.map → shield-alert-C6vEcK-g.js.map} +1 -1
- package/bizar-dash/dist/assets/{trash-2-CL4khSRv.js → trash-2-DZDjEnNh.js} +1 -1
- package/bizar-dash/dist/assets/{trash-2-CL4khSRv.js.map → trash-2-DZDjEnNh.js.map} +1 -1
- package/bizar-dash/dist/assets/{trending-up-CSJJhWTS.js → trending-up-DMj-AJVf.js} +1 -1
- package/bizar-dash/dist/assets/{trending-up-CSJJhWTS.js.map → trending-up-DMj-AJVf.js.map} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-BPLb7uLt.js → triangle-alert-_2xe_tl4.js} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-BPLb7uLt.js.map → triangle-alert-_2xe_tl4.js.map} +1 -1
- package/bizar-dash/dist/assets/{upload-Cww6MvFq.js → upload-DdDljAeV.js} +1 -1
- package/bizar-dash/dist/assets/{upload-Cww6MvFq.js.map → upload-DdDljAeV.js.map} +1 -1
- package/bizar-dash/dist/assets/{zap-DmhVUzRA.js → zap-mHsgh0FP.js} +1 -1
- package/bizar-dash/dist/assets/{zap-DmhVUzRA.js.map → zap-mHsgh0FP.js.map} +1 -1
- package/bizar-dash/dist/index.html +1 -1
- package/bizar-dash/src/server/api.mjs +13 -6
- package/bizar-dash/src/server/artifacts-store.mjs +120 -14
- package/bizar-dash/src/server/claude-artifacts.mjs +281 -0
- package/bizar-dash/src/server/diagnostics-store.mjs +5 -35
- package/bizar-dash/src/server/mod-security.mjs +1 -2
- package/bizar-dash/src/server/providers-store.mjs +1 -1
- package/bizar-dash/src/server/routes/_shared.mjs +0 -17
- package/bizar-dash/src/server/routes/artifacts.mjs +42 -6
- package/bizar-dash/src/server/routes/audit.mjs +78 -0
- package/bizar-dash/src/server/routes/decisions.mjs +78 -0
- package/bizar-dash/src/server/routes/model-router.mjs +158 -0
- package/bizar-dash/src/server/routes/model-router.test.mjs +104 -0
- package/bizar-dash/src/server/routes/sessions.mjs +80 -0
- package/bizar-dash/src/server/server.mjs +1 -27
- package/bizar-dash/src/server/sprint.test.mjs +163 -0
- package/bizar-dash/src/web/v8/views/Artifacts/ArtifactsView.tsx +232 -21
- package/bizar-dash/src/web/v8/views/Artifacts/ClaudeArtifactView.tsx +179 -0
- package/bizar-dash/tests/cli-bugfixes.test.mjs +1 -1
- package/bizar-dash/tests/cli-error-visibility.test.mjs +1 -1
- package/bizar-dash/tests/cli-refactor.test.mjs +0 -1
- package/bizar-dash/tests/diagnostics-store.test.mjs +0 -1
- package/cli/bin.mjs +1 -15
- package/cli/cli-commands-validation.test.mjs +1 -1
- package/cli/commands/lightrag.mjs +1 -1
- package/cli/commands/util.mjs +1 -1
- package/cli/copy.mjs +1 -47
- package/cli/doctor.mjs +3 -3
- package/cli/install.mjs +3 -37
- package/cli/service-controller.mjs +0 -192
- package/cli/service-env.mjs +2 -9
- package/cli/utils.mjs +0 -7
- package/package.json +1 -1
- package/packages/sdk/dist/agent/cron.d.ts +44 -0
- package/packages/sdk/dist/agent/cron.js +79 -0
- package/packages/sdk/dist/agent/heartbeat.d.ts +43 -0
- package/packages/sdk/dist/agent/heartbeat.js +116 -0
- package/packages/sdk/dist/index.d.ts +3 -0
- package/packages/sdk/dist/index.js +5 -0
- package/packages/sdk/dist/learning/decisions.d.ts +46 -0
- package/packages/sdk/dist/learning/decisions.js +132 -0
- package/packages/sdk/dist/learning/index.d.ts +8 -0
- package/packages/sdk/dist/learning/index.js +8 -0
- package/packages/sdk/dist/learning/instincts.d.ts +38 -0
- package/packages/sdk/dist/learning/instincts.js +139 -0
- package/packages/sdk/dist/mcp/server.js +119 -1
- package/packages/sdk/dist/router/agent-model-registry.d.ts +89 -0
- package/packages/sdk/dist/router/agent-model-registry.js +144 -0
- package/packages/sdk/dist/router/index.d.ts +1 -0
- package/packages/sdk/dist/router/index.js +1 -0
- package/packages/sdk/package.json +3 -2
- package/scripts/audit.mjs +388 -0
- package/scripts/audit.test.mjs +149 -0
- package/scripts/check-deps.mjs +0 -24
- package/scripts/eval-gate.mjs +134 -0
- package/scripts/eval-gate.test.mjs +138 -0
- package/scripts/feature-state-machine.mjs +178 -0
- package/scripts/feature-state-machine.test.mjs +135 -0
- package/scripts/spec-dedup.test.mjs +124 -0
- package/scripts/sprint.mjs +213 -0
- package/scripts/worktree-setup.sh +79 -0
- package/bizar-dash/dist/assets/ArtifactsView-CDIhPBAx.js +0 -6
- package/bizar-dash/dist/assets/ArtifactsView-CDIhPBAx.js.map +0 -1
package/bizar-dash/dist/assets/{ProjectsView-DhX5lzHS.js.map → ProjectsView-Soxtmpet.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectsView-DhX5lzHS.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/folder-plus.js","../../../node_modules/lucide-react/dist/esm/icons/scan-search.js","../../src/web/v8/views/Projects/ProjectsView.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 FolderPlus = createLucideIcon(\"FolderPlus\", [\n [\"path\", { d: \"M12 10v6\", key: \"1bos4e\" }],\n [\"path\", { d: \"M9 13h6\", key: \"1uhe8q\" }],\n [\n \"path\",\n {\n d: \"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\",\n key: \"1kt360\"\n }\n ]\n]);\n\nexport { FolderPlus as default };\n//# sourceMappingURL=folder-plus.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ScanSearch = createLucideIcon(\"ScanSearch\", [\n [\"path\", { d: \"M3 7V5a2 2 0 0 1 2-2h2\", key: \"aa7l1z\" }],\n [\"path\", { d: \"M17 3h2a2 2 0 0 1 2 2v2\", key: \"4qcy5o\" }],\n [\"path\", { d: \"M21 17v2a2 2 0 0 1-2 2h-2\", key: \"6vwrx8\" }],\n [\"path\", { d: \"M7 21H5a2 2 0 0 1-2-2v-2\", key: \"ioqczr\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }],\n [\"path\", { d: \"m16 16-1.9-1.9\", key: \"1dq9hf\" }]\n]);\n\nexport { ScanSearch as default };\n//# sourceMappingURL=scan-search.js.map\n","/**\n * v8/views/Projects/ProjectsView.tsx — Sprint S39, v9.3.0.\n *\n * The project registry surface. Shows every registered project,\n * lets the user mark one active, add by path (Sheet form), and\n * remove (inline confirm). Two utility actions sit in the header:\n * - Auto-detect: POST /api/projects/auto-detect (adds cwd)\n * - Scan: POST /api/projects/scan (walks the configured\n * dashboard.projectsDirectory and adds any new\n * roots it finds).\n *\n * Live refresh on the `project:change` WS event the server already\n * broadcasts from routes/projects.mjs.\n */\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { FolderPlus, RefreshCcw, ScanSearch, Sparkles, Trash2 } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { ListHeader } from '../../ui/data/ListHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { useWsMessage } from '../../data/useWebSocket.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { Project, WsMessage } from '../../data/types.js';\n\ninterface ProjectsPayload {\n projects: Project[];\n}\n\nexport function ProjectsView(): JSX.Element {\n const payload = useFetch<ProjectsPayload>('/api/projects');\n const [adding, setAdding] = useState<boolean>(false);\n const [newPath, setNewPath] = useState<string>('');\n const [newName, setNewName] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);\n\n const projects = payload.data?.projects ?? [];\n const activeId = projects.find((p) => p.active)?.id ?? null;\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n useWsMessage('project:change', refresh);\n\n const add = async (): Promise<void> => {\n const path = newPath.trim();\n if (!path || busy) return;\n setBusy(true);\n setError(null);\n try {\n await fetchJson<Project>('/api/projects', {\n method: 'POST',\n body: { path, name: newName.trim() || null },\n });\n setNewPath('');\n setNewName('');\n setAdding(false);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n const activate = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/projects/${id}/activate`, { method: 'POST', body: {} });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const remove = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/projects/${id}`, { method: 'DELETE' });\n setConfirmDeleteId(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const autoDetect = async (): Promise<void> => {\n setError(null);\n try {\n await fetchJson('/api/projects/auto-detect', { method: 'POST', body: {} });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const scan = async (): Promise<void> => {\n setError(null);\n try {\n await fetchJson('/api/projects/scan', { method: 'POST', body: {} });\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=\"projects-view\">\n <ViewHeader\n title=\"Projects\"\n description=\"Registered project roots. One is active at a time — every active-project endpoint scopes to it.\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"projects-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void scan()} data-testid=\"projects-scan\">\n <ScanSearch size={14} aria-hidden /> Scan configured dir\n </Button>\n <Button variant=\"ghost\" onClick={() => void autoDetect()} data-testid=\"projects-auto-detect\">\n <Sparkles size={14} aria-hidden /> Auto-detect cwd\n </Button>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"projects-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"projects-add\">\n <FolderPlus size={14} aria-hidden /> Add project\n </Button>\n </Inline>\n }\n />\n <ListHeader title=\"Registered\" count={projects.length} testid=\"projects-list-header\" />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && projects.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 36 }} />\n <Skeleton style={{ height: 36 }} />\n </Stack>\n ) : projects.length === 0 ? (\n <EmptyState\n icon={<FolderPlus size={28} aria-hidden />}\n title=\"No projects yet\"\n description=\"Add a path, auto-detect the server cwd, or scan the configured projects directory.\"\n />\n ) : (\n <Stack gap={2}>\n {projects.map((p) => {\n const isActive = p.id === activeId;\n const isConfirmingDelete = confirmDeleteId === p.id;\n return (\n <div\n key={p.id}\n data-testid={`project-row-${p.id}`}\n style={{\n padding: 'var(--space-3)',\n borderRadius: 'var(--radius-md)',\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 }}\n >\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>\n {p.name || p.path.split('/').pop() || p.id}\n </strong>\n {isActive && <Badge tone=\"success\">Active</Badge>}\n </Inline>\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', overflowWrap: 'anywhere' }}>\n {p.path}\n </span>\n </Stack>\n <Inline gap={1}>\n {!isActive && (\n <Button variant=\"primary\" onClick={() => void activate(p.id)} data-testid={`project-activate-${p.id}`}>\n Activate\n </Button>\n )}\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDeleteId((cur) => (cur === p.id ? null : p.id))}\n data-testid={`project-delete-${p.id}`}\n aria-label={`Remove project ${p.id}`}\n >\n <Trash2 size={14} aria-hidden /> Remove\n </Button>\n </Inline>\n </Inline>\n {isConfirmingDelete && (\n <Inline gap={1} style={{ marginTop: 'var(--space-2)' }}>\n <Button variant=\"danger\" onClick={() => void remove(p.id)} data-testid={`project-confirm-delete-${p.id}`}>\n Confirm remove\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDeleteId(null)} data-testid={`project-cancel-delete-${p.id}`}>\n Cancel\n </Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={adding} onOpenChange={setAdding}>\n <SheetContent side=\"right\" title=\"Add project\" description=\"Register an existing directory as a project root.\">\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)' }}>Path</span>\n <Input\n placeholder=\"/absolute/path/to/project\"\n value={newPath}\n data-testid=\"projects-add-path\"\n onChange={(e) => setNewPath((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)' }}>Display name (optional)</span>\n <Input\n placeholder=\"My project\"\n value={newName}\n data-testid=\"projects-add-name\"\n onChange={(e) => setNewName((e.target as HTMLInputElement).value)}\n />\n </label>\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" data-testid=\"projects-add-cancel\">Cancel</Button>\n </SheetClose>\n <Button variant=\"primary\" onClick={() => void add()} disabled={busy || newPath.trim() === ''} data-testid=\"projects-add-submit\">\n Add\n </Button>\n </Inline>\n </Stack>\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}"],"names":["FolderPlus","createLucideIcon","ScanSearch","ProjectsView","payload","useFetch","adding","setAdding","useState","newPath","setNewPath","newName","setNewName","busy","setBusy","error","setError","confirmDeleteId","setConfirmDeleteId","projects","_a","activeId","_b","p","refresh","useCallback","useWsMessage","add","path","fetchJson","err","FetchError","activate","id","remove","autoDetect","scan","jsxs","Stack","jsx","ViewHeader","Inline","Button","Sparkles","RefreshCcw","ListHeader","Card","CardBody","Skeleton","EmptyState","isActive","isConfirmingDelete","Badge","cur","Trash2","Sheet","SheetContent","Input","e","SheetClose"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"ProjectsView-Soxtmpet.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/folder-plus.js","../../../node_modules/lucide-react/dist/esm/icons/scan-search.js","../../src/web/v8/views/Projects/ProjectsView.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 FolderPlus = createLucideIcon(\"FolderPlus\", [\n [\"path\", { d: \"M12 10v6\", key: \"1bos4e\" }],\n [\"path\", { d: \"M9 13h6\", key: \"1uhe8q\" }],\n [\n \"path\",\n {\n d: \"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\",\n key: \"1kt360\"\n }\n ]\n]);\n\nexport { FolderPlus as default };\n//# sourceMappingURL=folder-plus.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ScanSearch = createLucideIcon(\"ScanSearch\", [\n [\"path\", { d: \"M3 7V5a2 2 0 0 1 2-2h2\", key: \"aa7l1z\" }],\n [\"path\", { d: \"M17 3h2a2 2 0 0 1 2 2v2\", key: \"4qcy5o\" }],\n [\"path\", { d: \"M21 17v2a2 2 0 0 1-2 2h-2\", key: \"6vwrx8\" }],\n [\"path\", { d: \"M7 21H5a2 2 0 0 1-2-2v-2\", key: \"ioqczr\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }],\n [\"path\", { d: \"m16 16-1.9-1.9\", key: \"1dq9hf\" }]\n]);\n\nexport { ScanSearch as default };\n//# sourceMappingURL=scan-search.js.map\n","/**\n * v8/views/Projects/ProjectsView.tsx — Sprint S39, v9.3.0.\n *\n * The project registry surface. Shows every registered project,\n * lets the user mark one active, add by path (Sheet form), and\n * remove (inline confirm). Two utility actions sit in the header:\n * - Auto-detect: POST /api/projects/auto-detect (adds cwd)\n * - Scan: POST /api/projects/scan (walks the configured\n * dashboard.projectsDirectory and adds any new\n * roots it finds).\n *\n * Live refresh on the `project:change` WS event the server already\n * broadcasts from routes/projects.mjs.\n */\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { FolderPlus, RefreshCcw, ScanSearch, Sparkles, Trash2 } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { ListHeader } from '../../ui/data/ListHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { useWsMessage } from '../../data/useWebSocket.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { Project, WsMessage } from '../../data/types.js';\n\ninterface ProjectsPayload {\n projects: Project[];\n}\n\nexport function ProjectsView(): JSX.Element {\n const payload = useFetch<ProjectsPayload>('/api/projects');\n const [adding, setAdding] = useState<boolean>(false);\n const [newPath, setNewPath] = useState<string>('');\n const [newName, setNewName] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);\n\n const projects = payload.data?.projects ?? [];\n const activeId = projects.find((p) => p.active)?.id ?? null;\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n useWsMessage('project:change', refresh);\n\n const add = async (): Promise<void> => {\n const path = newPath.trim();\n if (!path || busy) return;\n setBusy(true);\n setError(null);\n try {\n await fetchJson<Project>('/api/projects', {\n method: 'POST',\n body: { path, name: newName.trim() || null },\n });\n setNewPath('');\n setNewName('');\n setAdding(false);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n const activate = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/projects/${id}/activate`, { method: 'POST', body: {} });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const remove = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/projects/${id}`, { method: 'DELETE' });\n setConfirmDeleteId(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const autoDetect = async (): Promise<void> => {\n setError(null);\n try {\n await fetchJson('/api/projects/auto-detect', { method: 'POST', body: {} });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const scan = async (): Promise<void> => {\n setError(null);\n try {\n await fetchJson('/api/projects/scan', { method: 'POST', body: {} });\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=\"projects-view\">\n <ViewHeader\n title=\"Projects\"\n description=\"Registered project roots. One is active at a time — every active-project endpoint scopes to it.\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"projects-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void scan()} data-testid=\"projects-scan\">\n <ScanSearch size={14} aria-hidden /> Scan configured dir\n </Button>\n <Button variant=\"ghost\" onClick={() => void autoDetect()} data-testid=\"projects-auto-detect\">\n <Sparkles size={14} aria-hidden /> Auto-detect cwd\n </Button>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"projects-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"projects-add\">\n <FolderPlus size={14} aria-hidden /> Add project\n </Button>\n </Inline>\n }\n />\n <ListHeader title=\"Registered\" count={projects.length} testid=\"projects-list-header\" />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && projects.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 36 }} />\n <Skeleton style={{ height: 36 }} />\n </Stack>\n ) : projects.length === 0 ? (\n <EmptyState\n icon={<FolderPlus size={28} aria-hidden />}\n title=\"No projects yet\"\n description=\"Add a path, auto-detect the server cwd, or scan the configured projects directory.\"\n />\n ) : (\n <Stack gap={2}>\n {projects.map((p) => {\n const isActive = p.id === activeId;\n const isConfirmingDelete = confirmDeleteId === p.id;\n return (\n <div\n key={p.id}\n data-testid={`project-row-${p.id}`}\n style={{\n padding: 'var(--space-3)',\n borderRadius: 'var(--radius-md)',\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 }}\n >\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>\n {p.name || p.path.split('/').pop() || p.id}\n </strong>\n {isActive && <Badge tone=\"success\">Active</Badge>}\n </Inline>\n <span style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', overflowWrap: 'anywhere' }}>\n {p.path}\n </span>\n </Stack>\n <Inline gap={1}>\n {!isActive && (\n <Button variant=\"primary\" onClick={() => void activate(p.id)} data-testid={`project-activate-${p.id}`}>\n Activate\n </Button>\n )}\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDeleteId((cur) => (cur === p.id ? null : p.id))}\n data-testid={`project-delete-${p.id}`}\n aria-label={`Remove project ${p.id}`}\n >\n <Trash2 size={14} aria-hidden /> Remove\n </Button>\n </Inline>\n </Inline>\n {isConfirmingDelete && (\n <Inline gap={1} style={{ marginTop: 'var(--space-2)' }}>\n <Button variant=\"danger\" onClick={() => void remove(p.id)} data-testid={`project-confirm-delete-${p.id}`}>\n Confirm remove\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDeleteId(null)} data-testid={`project-cancel-delete-${p.id}`}>\n Cancel\n </Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={adding} onOpenChange={setAdding}>\n <SheetContent side=\"right\" title=\"Add project\" description=\"Register an existing directory as a project root.\">\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)' }}>Path</span>\n <Input\n placeholder=\"/absolute/path/to/project\"\n value={newPath}\n data-testid=\"projects-add-path\"\n onChange={(e) => setNewPath((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)' }}>Display name (optional)</span>\n <Input\n placeholder=\"My project\"\n value={newName}\n data-testid=\"projects-add-name\"\n onChange={(e) => setNewName((e.target as HTMLInputElement).value)}\n />\n </label>\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" data-testid=\"projects-add-cancel\">Cancel</Button>\n </SheetClose>\n <Button variant=\"primary\" onClick={() => void add()} disabled={busy || newPath.trim() === ''} data-testid=\"projects-add-submit\">\n Add\n </Button>\n </Inline>\n </Stack>\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}"],"names":["FolderPlus","createLucideIcon","ScanSearch","ProjectsView","payload","useFetch","adding","setAdding","useState","newPath","setNewPath","newName","setNewName","busy","setBusy","error","setError","confirmDeleteId","setConfirmDeleteId","projects","_a","activeId","_b","p","refresh","useCallback","useWsMessage","add","path","fetchJson","err","FetchError","activate","id","remove","autoDetect","scan","jsxs","Stack","jsx","ViewHeader","Inline","Button","Sparkles","RefreshCcw","ListHeader","Card","CardBody","Skeleton","EmptyState","isActive","isConfirmingDelete","Badge","cur","Trash2","Sheet","SheetContent","Input","e","SheetClose"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as c,j as r}from"./cmdk-DVxytz9i.js";import{c as P,u as R,i as n,S as m,I as l,d,w as B,h as z,j as M,F as u}from"./main-
|
|
1
|
+
import{r as c,j as r}from"./cmdk-DVxytz9i.js";import{c as P,u as R,i as n,S as m,I as l,d,w as B,h as z,j as M,F as u}from"./main-CokHAXWM.js";import{V as N}from"./ViewHeader-BzYZ3m-e.js";import{L as F}from"./ListHeader-TjPJrUfY.js";import{C as x,b as j}from"./Card-B0imhxMk.js";import{E as H}from"./EmptyState-BjgVOrcO.js";import{R as _}from"./refresh-ccw-DNrXX9gB.js";import{P as J}from"./plus-DENm0hqV.js";import{R as W}from"./rotate-cw-xpPJw9LP.js";import{P as Y}from"./pencil-eq5IqBmU.js";import{P as q}from"./power-off-D47cOnG_.js";import{P as G}from"./power-DLjXF7zE.js";import{T as Q}from"./trash-2-DZDjEnNh.js";/**
|
|
2
2
|
* @license lucide-react v0.460.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
package/bizar-dash/dist/assets/{ProvidersView-CJMX7jm9.js.map → ProvidersView-DaCEV9pM.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProvidersView-CJMX7jm9.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/key-round.js","../../../node_modules/lucide-react/dist/esm/icons/star.js","../../src/web/v8/views/Providers/ProvidersView.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 KeyRound = createLucideIcon(\"KeyRound\", [\n [\n \"path\",\n {\n d: \"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z\",\n key: \"1s6t7t\"\n }\n ],\n [\"circle\", { cx: \"16.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"w0ekpg\" }]\n]);\n\nexport { KeyRound as default };\n//# sourceMappingURL=key-round.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Star = createLucideIcon(\"Star\", [\n [\n \"path\",\n {\n d: \"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\",\n key: \"r04s7s\"\n }\n ]\n]);\n\nexport { Star as default };\n//# sourceMappingURL=star.js.map\n","/**\n * v8/views/Providers/ProvidersView.tsx — Sprint S42, v9.3.0.\n *\n * Provider list pulled from /api/providers (aggregated). Per-row:\n * - active-key card (GET /api/providers/:id/active-key) with masked\n * key preview + label + status\n * - rotate button (POST /api/providers/:id/rotate) with inline confirm\n *\n * Header actions:\n * - Active default card (GET /api/providers/active)\n * - Auto-detect (GET /api/providers/auto-detect)\n *\n * Inline confirm row pattern; no window.confirm.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { KeyRound, Pencil, Plus, Power, PowerOff, RotateCw, Sparkles, Star, Trash2, RefreshCcw, Cpu } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { ListHeader } from '../../ui/data/ListHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface Provider {\n id: string;\n name?: string;\n source?: string;\n baseURL?: string;\n models?: string[];\n keys?: ProviderKey[];\n active?: boolean;\n enabled?: boolean;\n}\n\ninterface ProviderKey {\n envVar?: string;\n label?: string;\n status?: string;\n}\n\ninterface ActiveKey {\n envVar: string;\n label?: string;\n status?: string;\n keyPreview: string;\n keySet: boolean;\n}\n\ninterface ActiveDefault {\n providerId: string | null;\n modelId: string | null;\n source?: string | null;\n}\n\nexport function ProvidersView(): JSX.Element {\n const payload = useFetch<{ providers: Provider[]; count: number }>('/api/providers');\n const activePayload = useFetch<ActiveDefault>('/api/providers/active');\n const [confirmRotate, setConfirmRotate] = useState<string | null>(null);\n const [activeKeys, setActiveKeys] = useState<Record<string, ActiveKey | null>>({});\n const [error, setError] = useState<string | null>(null);\n const [autoDetect, setAutoDetect] = useState<{ providers: Provider[] } | null>(null);\n const [probing, setProbing] = useState<boolean>(false);\n\n const providers = useMemo<Provider[]>(() => payload.data?.providers ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); void activePayload.refetch(); }, [payload, activePayload]);\n\n // Fetch the active key for each provider (lazy, in parallel).\n useEffect(() => {\n if (!providers.length) return;\n let cancelled = false;\n (async () => {\n const results = await Promise.all(\n providers.map(async (p) => {\n try {\n const r = await fetchJson<{ ok: boolean; active: ActiveKey } | { ok: false; error: string }>(`/api/providers/${p.id}/active-key`);\n return [p.id, ('active' in r ? r.active : null)] as const;\n } catch {\n return [p.id, null] as const;\n }\n }),\n );\n if (!cancelled) {\n const map: Record<string, ActiveKey | null> = {};\n for (const [id, ak] of results) map[id] = ak;\n setActiveKeys(map);\n }\n })();\n return () => { cancelled = true; };\n }, [providers]);\n\n const rotate = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/providers/${id}/rotate`, { method: 'POST' });\n setConfirmRotate(null);\n refresh();\n // Re-fetch the new active key for this row.\n try {\n const r = await fetchJson<{ ok: boolean; active: ActiveKey }>(`/api/providers/${id}/active-key`);\n setActiveKeys((m) => ({ ...m, [id]: r.active }));\n } catch { /* ignore */ }\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const addKey = async (id: string): Promise<void> => {\n const envVar = window.prompt(`Env var name to add to ${id} (e.g. ${id.toUpperCase()}_KEY_2)`);\n if (!envVar?.trim()) return;\n const label = window.prompt('Label (optional)') || undefined;\n setError(null);\n try {\n await fetchJson(`/api/providers/${id}/keys`, { method: 'POST', body: { envVar, label } });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const runAutoDetect = async (): Promise<void> => {\n setProbing(true);\n setError(null);\n try {\n const r = await fetchJson<{ providers: Provider[] }>('/api/providers/auto-detect');\n setAutoDetect({ providers: r.providers });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setProbing(false);\n }\n };\n\n const createProvider = async (): Promise<void> => {\n const id = window.prompt('Provider id (lowercase, e.g. openai)');\n if (!id?.trim()) return;\n const name = window.prompt('Display name') || id;\n const baseURL = window.prompt('Base URL (optional)') || '';\n const apiKey = window.prompt('API key or env:VAR marker') || '';\n setError(null);\n try {\n await fetchJson('/api/providers', { method: 'POST', body: { id, name, baseURL, apiKey } });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const editProvider = async (p: Provider): Promise<void> => {\n const name = window.prompt(`Rename ${p.id}`, p.name || p.id);\n if (!name?.trim()) return;\n const baseURL = window.prompt('Base URL', p.baseURL || '');\n setError(null);\n try {\n await fetchJson(`/api/providers/${encodeURIComponent(p.id)}`, {\n method: 'PUT',\n body: { name, baseURL: baseURL ?? '' },\n });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const deleteProvider = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/providers/${encodeURIComponent(id)}`, { method: 'DELETE' });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const toggleEnabled = async (id: string, currentlyEnabled: boolean): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/providers/${encodeURIComponent(id)}/${currentlyEnabled ? 'disable' : 'enable'}`, { method: 'POST' });\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=\"providers-view\">\n <ViewHeader\n title=\"Providers\"\n description=\"Configured LLM providers + active key rotation.\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"providers-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"providers-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => void runAutoDetect()} disabled={probing} data-testid=\"providers-auto-detect\">\n <Sparkles size={14} aria-hidden /> {probing ? 'Probing…' : 'Auto-detect'}\n </Button>\n <Button variant=\"primary\" onClick={() => void createProvider()} data-testid=\"providers-create\">\n <Plus size={14} aria-hidden /> New provider\n </Button>\n </Inline>\n }\n />\n <ListHeader\n title=\"Configured\"\n count={providers.length}\n description={activePayload.data?.providerId ? `active: ${activePayload.data.providerId}` : undefined}\n testid=\"providers-list-header\"\n />\n\n {activePayload.data && (activePayload.data.providerId !== null || activePayload.data.modelId !== null) && (\n <Card variant=\"default\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <Star size={14} aria-hidden style={{ color: 'var(--accent)' }} />\n <strong>Active default:</strong>\n <code data-testid=\"providers-active-provider\">{activePayload.data.providerId ?? '—'}</code>\n <span style={{ color: 'var(--fg-muted)' }}>·</span>\n <code data-testid=\"providers-active-model\">{activePayload.data.modelId ?? '—'}</code>\n {activePayload.data.source && (\n <span style={{ color: 'var(--fg-subtle)', fontSize: 'var(--fs-12)' }}>({activePayload.data.source})</span>\n )}\n </Inline>\n </Inline>\n </CardBody>\n </Card>\n )}\n\n {autoDetect !== null && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Auto-detect result</strong>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {autoDetect.providers.length} candidate{autoDetect.providers.length === 1 ? '' : 's'} from env + config.\n </span>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && providers.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 56 }} />\n <Skeleton style={{ height: 56 }} />\n </Stack>\n ) : providers.length === 0 ? (\n <EmptyState icon={<Cpu size={28} aria-hidden />} title=\"No providers\" description=\"Run Auto-detect or add via Config → Providers.\" />\n ) : (\n <Stack gap={1}>\n {providers.map((p) => {\n const isConfirming = confirmRotate === p.id;\n const ak = activeKeys[p.id];\n return (\n <div\n key={p.id}\n data-testid={`provider-row-${p.id}`}\n style={{\n padding: 'var(--space-3)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0}>\n <Inline align=\"center\" gap={2}>\n <strong>{p.name || p.id}</strong>\n <code style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{p.id}</code>\n {p.source && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>· {p.source}</span>}\n {p.active && (\n <span data-testid={`provider-active-${p.id}`} style={{ fontSize: 'var(--fs-11)', color: 'var(--success)', fontWeight: 600 }}>ACTIVE</span>\n )}\n </Inline>\n {p.baseURL && <code style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{p.baseURL}</code>}\n </Stack>\n <Inline gap={1}>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmRotate((cur) => (cur === p.id ? null : p.id))}\n data-testid={`provider-rotate-${p.id}`}\n aria-label={`Rotate ${p.id}`}\n disabled={!p.keys || p.keys.length < 2}\n title={!p.keys || p.keys.length < 2 ? 'Need ≥2 keys to rotate' : 'Rotate active key'}\n >\n <RotateCw size={14} aria-hidden /> Rotate\n </Button>\n <Button\n variant=\"primary\"\n onClick={() => void addKey(p.id)}\n data-testid={`provider-add-key-${p.id}`}\n aria-label={`Add key to ${p.id}`}\n >\n <KeyRound size={14} aria-hidden /> Add key\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void editProvider(p)}\n data-testid={`provider-edit-${p.id}`}\n aria-label={`Edit ${p.id}`}\n >\n <Pencil size={14} aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void toggleEnabled(p.id, p.enabled ?? true)}\n data-testid={`provider-toggle-${p.id}`}\n aria-label={(p.enabled ?? true) ? `Disable ${p.id}` : `Enable ${p.id}`}\n >\n {(p.enabled ?? true) ? <PowerOff size={14} aria-hidden /> : <Power size={14} aria-hidden />}\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void deleteProvider(p.id)}\n data-testid={`provider-delete-${p.id}`}\n aria-label={`Delete ${p.id}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n\n {/* Active-key sub-row */}\n <div data-testid={`provider-active-key-${p.id}`} style={{ marginTop: 'var(--space-2)', padding: 'var(--space-2)', background: 'var(--surface-1)', borderRadius: 'var(--radius-sm)' }}>\n <Inline align=\"center\" gap={2}>\n <KeyRound size={12} aria-hidden style={{ color: 'var(--fg-muted)' }} />\n {ak === undefined ? (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-subtle)' }}>Probing active key…</span>\n ) : ak === null ? (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-subtle)' }}>No active key</span>\n ) : (\n <Inline align=\"center\" gap={2} data-testid={`provider-active-key-detail-${p.id}`}>\n <code style={{ fontSize: 'var(--fs-12)' }}>{ak.envVar}</code>\n {ak.label && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>· {ak.label}</span>}\n {ak.status && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>· {ak.status}</span>}\n <code style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{ak.keyPreview}</code>\n </Inline>\n )}\n </Inline>\n </div>\n\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"primary\" onClick={() => void rotate(p.id)} data-testid={`provider-confirm-rotate-${p.id}`}>\n Confirm rotate\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmRotate(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["KeyRound","createLucideIcon","Star","ProvidersView","payload","useFetch","activePayload","confirmRotate","setConfirmRotate","useState","activeKeys","setActiveKeys","error","setError","autoDetect","setAutoDetect","probing","setProbing","providers","useMemo","_a","refresh","useCallback","useEffect","cancelled","results","p","r","fetchJson","map","id","ak","rotate","m","err","FetchError","addKey","envVar","label","runAutoDetect","createProvider","name","baseURL","apiKey","editProvider","deleteProvider","toggleEnabled","currentlyEnabled","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCcw","Sparkles","Plus","ListHeader","Card","CardBody","Skeleton","EmptyState","Cpu","isConfirming","cur","RotateCw","Pencil","PowerOff","Power","Trash2"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"ProvidersView-DaCEV9pM.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/key-round.js","../../../node_modules/lucide-react/dist/esm/icons/star.js","../../src/web/v8/views/Providers/ProvidersView.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 KeyRound = createLucideIcon(\"KeyRound\", [\n [\n \"path\",\n {\n d: \"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z\",\n key: \"1s6t7t\"\n }\n ],\n [\"circle\", { cx: \"16.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"w0ekpg\" }]\n]);\n\nexport { KeyRound as default };\n//# sourceMappingURL=key-round.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Star = createLucideIcon(\"Star\", [\n [\n \"path\",\n {\n d: \"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\",\n key: \"r04s7s\"\n }\n ]\n]);\n\nexport { Star as default };\n//# sourceMappingURL=star.js.map\n","/**\n * v8/views/Providers/ProvidersView.tsx — Sprint S42, v9.3.0.\n *\n * Provider list pulled from /api/providers (aggregated). Per-row:\n * - active-key card (GET /api/providers/:id/active-key) with masked\n * key preview + label + status\n * - rotate button (POST /api/providers/:id/rotate) with inline confirm\n *\n * Header actions:\n * - Active default card (GET /api/providers/active)\n * - Auto-detect (GET /api/providers/auto-detect)\n *\n * Inline confirm row pattern; no window.confirm.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { KeyRound, Pencil, Plus, Power, PowerOff, RotateCw, Sparkles, Star, Trash2, RefreshCcw, Cpu } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { ListHeader } from '../../ui/data/ListHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface Provider {\n id: string;\n name?: string;\n source?: string;\n baseURL?: string;\n models?: string[];\n keys?: ProviderKey[];\n active?: boolean;\n enabled?: boolean;\n}\n\ninterface ProviderKey {\n envVar?: string;\n label?: string;\n status?: string;\n}\n\ninterface ActiveKey {\n envVar: string;\n label?: string;\n status?: string;\n keyPreview: string;\n keySet: boolean;\n}\n\ninterface ActiveDefault {\n providerId: string | null;\n modelId: string | null;\n source?: string | null;\n}\n\nexport function ProvidersView(): JSX.Element {\n const payload = useFetch<{ providers: Provider[]; count: number }>('/api/providers');\n const activePayload = useFetch<ActiveDefault>('/api/providers/active');\n const [confirmRotate, setConfirmRotate] = useState<string | null>(null);\n const [activeKeys, setActiveKeys] = useState<Record<string, ActiveKey | null>>({});\n const [error, setError] = useState<string | null>(null);\n const [autoDetect, setAutoDetect] = useState<{ providers: Provider[] } | null>(null);\n const [probing, setProbing] = useState<boolean>(false);\n\n const providers = useMemo<Provider[]>(() => payload.data?.providers ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); void activePayload.refetch(); }, [payload, activePayload]);\n\n // Fetch the active key for each provider (lazy, in parallel).\n useEffect(() => {\n if (!providers.length) return;\n let cancelled = false;\n (async () => {\n const results = await Promise.all(\n providers.map(async (p) => {\n try {\n const r = await fetchJson<{ ok: boolean; active: ActiveKey } | { ok: false; error: string }>(`/api/providers/${p.id}/active-key`);\n return [p.id, ('active' in r ? r.active : null)] as const;\n } catch {\n return [p.id, null] as const;\n }\n }),\n );\n if (!cancelled) {\n const map: Record<string, ActiveKey | null> = {};\n for (const [id, ak] of results) map[id] = ak;\n setActiveKeys(map);\n }\n })();\n return () => { cancelled = true; };\n }, [providers]);\n\n const rotate = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/providers/${id}/rotate`, { method: 'POST' });\n setConfirmRotate(null);\n refresh();\n // Re-fetch the new active key for this row.\n try {\n const r = await fetchJson<{ ok: boolean; active: ActiveKey }>(`/api/providers/${id}/active-key`);\n setActiveKeys((m) => ({ ...m, [id]: r.active }));\n } catch { /* ignore */ }\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const addKey = async (id: string): Promise<void> => {\n const envVar = window.prompt(`Env var name to add to ${id} (e.g. ${id.toUpperCase()}_KEY_2)`);\n if (!envVar?.trim()) return;\n const label = window.prompt('Label (optional)') || undefined;\n setError(null);\n try {\n await fetchJson(`/api/providers/${id}/keys`, { method: 'POST', body: { envVar, label } });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const runAutoDetect = async (): Promise<void> => {\n setProbing(true);\n setError(null);\n try {\n const r = await fetchJson<{ providers: Provider[] }>('/api/providers/auto-detect');\n setAutoDetect({ providers: r.providers });\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setProbing(false);\n }\n };\n\n const createProvider = async (): Promise<void> => {\n const id = window.prompt('Provider id (lowercase, e.g. openai)');\n if (!id?.trim()) return;\n const name = window.prompt('Display name') || id;\n const baseURL = window.prompt('Base URL (optional)') || '';\n const apiKey = window.prompt('API key or env:VAR marker') || '';\n setError(null);\n try {\n await fetchJson('/api/providers', { method: 'POST', body: { id, name, baseURL, apiKey } });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const editProvider = async (p: Provider): Promise<void> => {\n const name = window.prompt(`Rename ${p.id}`, p.name || p.id);\n if (!name?.trim()) return;\n const baseURL = window.prompt('Base URL', p.baseURL || '');\n setError(null);\n try {\n await fetchJson(`/api/providers/${encodeURIComponent(p.id)}`, {\n method: 'PUT',\n body: { name, baseURL: baseURL ?? '' },\n });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const deleteProvider = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/providers/${encodeURIComponent(id)}`, { method: 'DELETE' });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const toggleEnabled = async (id: string, currentlyEnabled: boolean): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/providers/${encodeURIComponent(id)}/${currentlyEnabled ? 'disable' : 'enable'}`, { method: 'POST' });\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=\"providers-view\">\n <ViewHeader\n title=\"Providers\"\n description=\"Configured LLM providers + active key rotation.\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"providers-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"providers-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => void runAutoDetect()} disabled={probing} data-testid=\"providers-auto-detect\">\n <Sparkles size={14} aria-hidden /> {probing ? 'Probing…' : 'Auto-detect'}\n </Button>\n <Button variant=\"primary\" onClick={() => void createProvider()} data-testid=\"providers-create\">\n <Plus size={14} aria-hidden /> New provider\n </Button>\n </Inline>\n }\n />\n <ListHeader\n title=\"Configured\"\n count={providers.length}\n description={activePayload.data?.providerId ? `active: ${activePayload.data.providerId}` : undefined}\n testid=\"providers-list-header\"\n />\n\n {activePayload.data && (activePayload.data.providerId !== null || activePayload.data.modelId !== null) && (\n <Card variant=\"default\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <Star size={14} aria-hidden style={{ color: 'var(--accent)' }} />\n <strong>Active default:</strong>\n <code data-testid=\"providers-active-provider\">{activePayload.data.providerId ?? '—'}</code>\n <span style={{ color: 'var(--fg-muted)' }}>·</span>\n <code data-testid=\"providers-active-model\">{activePayload.data.modelId ?? '—'}</code>\n {activePayload.data.source && (\n <span style={{ color: 'var(--fg-subtle)', fontSize: 'var(--fs-12)' }}>({activePayload.data.source})</span>\n )}\n </Inline>\n </Inline>\n </CardBody>\n </Card>\n )}\n\n {autoDetect !== null && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Auto-detect result</strong>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {autoDetect.providers.length} candidate{autoDetect.providers.length === 1 ? '' : 's'} from env + config.\n </span>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && providers.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 56 }} />\n <Skeleton style={{ height: 56 }} />\n </Stack>\n ) : providers.length === 0 ? (\n <EmptyState icon={<Cpu size={28} aria-hidden />} title=\"No providers\" description=\"Run Auto-detect or add via Config → Providers.\" />\n ) : (\n <Stack gap={1}>\n {providers.map((p) => {\n const isConfirming = confirmRotate === p.id;\n const ak = activeKeys[p.id];\n return (\n <div\n key={p.id}\n data-testid={`provider-row-${p.id}`}\n style={{\n padding: 'var(--space-3)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0}>\n <Inline align=\"center\" gap={2}>\n <strong>{p.name || p.id}</strong>\n <code style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{p.id}</code>\n {p.source && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>· {p.source}</span>}\n {p.active && (\n <span data-testid={`provider-active-${p.id}`} style={{ fontSize: 'var(--fs-11)', color: 'var(--success)', fontWeight: 600 }}>ACTIVE</span>\n )}\n </Inline>\n {p.baseURL && <code style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{p.baseURL}</code>}\n </Stack>\n <Inline gap={1}>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmRotate((cur) => (cur === p.id ? null : p.id))}\n data-testid={`provider-rotate-${p.id}`}\n aria-label={`Rotate ${p.id}`}\n disabled={!p.keys || p.keys.length < 2}\n title={!p.keys || p.keys.length < 2 ? 'Need ≥2 keys to rotate' : 'Rotate active key'}\n >\n <RotateCw size={14} aria-hidden /> Rotate\n </Button>\n <Button\n variant=\"primary\"\n onClick={() => void addKey(p.id)}\n data-testid={`provider-add-key-${p.id}`}\n aria-label={`Add key to ${p.id}`}\n >\n <KeyRound size={14} aria-hidden /> Add key\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void editProvider(p)}\n data-testid={`provider-edit-${p.id}`}\n aria-label={`Edit ${p.id}`}\n >\n <Pencil size={14} aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void toggleEnabled(p.id, p.enabled ?? true)}\n data-testid={`provider-toggle-${p.id}`}\n aria-label={(p.enabled ?? true) ? `Disable ${p.id}` : `Enable ${p.id}`}\n >\n {(p.enabled ?? true) ? <PowerOff size={14} aria-hidden /> : <Power size={14} aria-hidden />}\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void deleteProvider(p.id)}\n data-testid={`provider-delete-${p.id}`}\n aria-label={`Delete ${p.id}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n\n {/* Active-key sub-row */}\n <div data-testid={`provider-active-key-${p.id}`} style={{ marginTop: 'var(--space-2)', padding: 'var(--space-2)', background: 'var(--surface-1)', borderRadius: 'var(--radius-sm)' }}>\n <Inline align=\"center\" gap={2}>\n <KeyRound size={12} aria-hidden style={{ color: 'var(--fg-muted)' }} />\n {ak === undefined ? (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-subtle)' }}>Probing active key…</span>\n ) : ak === null ? (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-subtle)' }}>No active key</span>\n ) : (\n <Inline align=\"center\" gap={2} data-testid={`provider-active-key-detail-${p.id}`}>\n <code style={{ fontSize: 'var(--fs-12)' }}>{ak.envVar}</code>\n {ak.label && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>· {ak.label}</span>}\n {ak.status && <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>· {ak.status}</span>}\n <code style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>{ak.keyPreview}</code>\n </Inline>\n )}\n </Inline>\n </div>\n\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"primary\" onClick={() => void rotate(p.id)} data-testid={`provider-confirm-rotate-${p.id}`}>\n Confirm rotate\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmRotate(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["KeyRound","createLucideIcon","Star","ProvidersView","payload","useFetch","activePayload","confirmRotate","setConfirmRotate","useState","activeKeys","setActiveKeys","error","setError","autoDetect","setAutoDetect","probing","setProbing","providers","useMemo","_a","refresh","useCallback","useEffect","cancelled","results","p","r","fetchJson","map","id","ak","rotate","m","err","FetchError","addKey","envVar","label","runAutoDetect","createProvider","name","baseURL","apiKey","editProvider","deleteProvider","toggleEnabled","currentlyEnabled","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCcw","Sparkles","Plus","ListHeader","Card","CardBody","Skeleton","EmptyState","Cpu","isConfirming","cur","RotateCw","Pencil","PowerOff","Power","Trash2"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as d,j as e}from"./cmdk-DVxytz9i.js";import{u as P,a as U,S as r,d as l,h as $,I as m,B as u,i as p,F as f}from"./main-
|
|
1
|
+
import{r as d,j as e}from"./cmdk-DVxytz9i.js";import{u as P,a as U,S as r,d as l,h as $,I as m,B as u,i as p,F as f}from"./main-CokHAXWM.js";import{G as A}from"./Grid-qcvbhx6e.js";import{V as B}from"./ViewHeader-BzYZ3m-e.js";import{C as b,b as T}from"./Card-B0imhxMk.js";import{S as D}from"./Switch-CwXfsDii.js";import{T as L}from"./Textarea-BzIAwSlp.js";import{S as N,a as O}from"./Sheet-DnDid58j.js";import{I as x}from"./Input-Bgzxf_Hu.js";import{P as H}from"./plus-DENm0hqV.js";import{C as y}from"./clock-CejGoecX.js";import{P as k}from"./play-BoLrrcBA.js";import{R as V}from"./refresh-cw-CoAHDpeS.js";import{T as G}from"./trash-2-DZDjEnNh.js";import"./index-CASP1n-5.js";const w={interval:"Interval",cron:"Cron",once:"One-time"},M={interval:V,cron:y,once:k};function Y({sched:i}){return i.enabled?i.lastError?e.jsx(u,{tone:"danger",children:"error"}):i.lastRun===null?e.jsx(u,{tone:"info",children:"never run"}):e.jsx(u,{tone:"success",children:"active"}):e.jsx(u,{tone:"neutral",children:"disabled"})}function oe(){const i=P("/api/schedules"),[j,_]=d.useState([]),[a,s]=d.useState(null),[o,c]=d.useState(!1),[S,z]=d.useState(null),[C,h]=d.useState(null);U("schedules:change",d.useCallback(()=>{i.refetch()},[i]));const v=d.useMemo(()=>[...j,...i.data||[]],[j,i.data]),g=()=>{i.refetch()},E=async t=>{h(null);try{await p(`/api/schedules/${encodeURIComponent(t.id)}`,{method:"PATCH",body:{enabled:!t.enabled}}),g()}catch(n){h(n instanceof f?n.message:String(n))}},R=async t=>{h(null),c(!0);try{await p(`/api/schedules/${encodeURIComponent(t.id)}/run`,{method:"POST"}),g()}catch(n){h(n instanceof f?n.message:String(n))}finally{c(!1)}},I=async t=>{h(null),c(!0);try{await p(`/api/schedules/${encodeURIComponent(t)}`,{method:"DELETE"}),g()}catch(n){h(n instanceof f?n.message:String(n))}finally{c(!1)}},F=async()=>{if(!(!a||!a.name.trim()||!a.schedule.trim())){c(!0),z(null);try{const t={type:a.actionType};a.actionType==="agent"&&(t.prompt=a.prompt),a.actionType==="command"&&(t.command=a.prompt),a.id?await p(`/api/schedules/${encodeURIComponent(a.id)}`,{method:"PATCH",body:{name:a.name,type:a.type,schedule:a.schedule,timezone:a.timezone||"UTC",action:t}}):await p("/api/schedules",{method:"POST",body:{name:a.name,type:a.type,schedule:a.schedule,timezone:a.timezone||"UTC",action:t,enabled:!0}}),s(null),g()}catch(t){z(t instanceof f?t.message:String(t))}finally{c(!1)}}};return e.jsxs(r,{gap:5,"data-testid":"schedules-view",children:[e.jsx(B,{title:"Schedules",description:"Recurring and one-time jobs. Toggle enabled, run on demand, or create new.",actions:e.jsxs(l,{variant:"primary",size:"sm",onClick:()=>s({name:"",type:"interval",schedule:"1h",timezone:"UTC",actionType:"agent",prompt:""}),"data-testid":"schedules-new",children:[e.jsx(H,{size:14,"aria-hidden":!0})," New schedule"]})}),C!==null&&e.jsx("div",{role:"alert",style:{padding:"var(--space-2) var(--space-3)",background:"color-mix(in oklch, var(--danger) 12%, var(--surface-0))",border:"1px solid var(--danger)",borderRadius:"var(--radius-md)",fontSize:"var(--fs-12)",color:"var(--danger)"},children:C}),i.loading&&v.length===0?e.jsx($,{style:{height:240}}):v.length===0?e.jsx(b,{children:e.jsx(T,{children:e.jsxs(r,{gap:1,align:"center",children:[e.jsx(y,{size:32,"aria-hidden":!0,style:{color:"var(--fg-muted)"}}),e.jsx("strong",{children:"No schedules yet"}),e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-13)"},children:"Create one with the button above."})]})})}):e.jsx(r,{gap:3,children:v.map(t=>{const n=M[t.type]??y;return e.jsx(b,{"data-testid":`schedule-${t.id}`,children:e.jsx(T,{children:e.jsxs(A,{cols:4,gap:3,style:{alignItems:"center"},children:[e.jsxs(r,{gap:1,children:[e.jsxs(m,{align:"center",gap:2,children:[e.jsx(n,{size:12,"aria-hidden":!0,style:{color:"var(--fg-muted)"}}),e.jsx("strong",{style:{fontSize:"var(--fs-14)"},children:t.name})]}),e.jsxs(m,{gap:2,children:[e.jsx(u,{tone:"neutral",children:w[t.type]}),e.jsx(Y,{sched:t})]})]}),e.jsxs(r,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Schedule"}),e.jsx("code",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)"},children:t.schedule}),e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:t.timezone})]}),e.jsxs(r,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Next run"}),t.nextRun?e.jsx("code",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)"},children:new Date(t.nextRun).toLocaleString()}):e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"—"}),t.lastRun&&e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:["Last: ",new Date(t.lastRun).toLocaleDateString()]})]}),e.jsxs(m,{align:"center",gap:2,justify:"end",children:[e.jsx(l,{variant:"ghost",size:"sm",onClick:()=>s({id:t.id,name:t.name,type:t.type,schedule:t.schedule,timezone:t.timezone||"UTC",actionType:"agent",prompt:t.action&&t.action.prompt||""}),"data-testid":`schedule-edit-${t.id}`,title:"Edit",children:"Edit"}),e.jsx(l,{variant:"secondary",size:"sm",onClick:()=>{R(t)},disabled:o,"data-testid":`schedule-run-${t.id}`,title:"Run now",children:e.jsx(k,{size:12,"aria-hidden":!0})}),e.jsx(D,{checked:t.enabled,onCheckedChange:()=>{E(t)},"aria-label":`Toggle ${t.name} enabled`}),e.jsx(l,{variant:"danger",size:"sm",onClick:()=>{I(t.id)},disabled:o,"data-testid":`schedule-delete-${t.id}`,title:"Delete",children:e.jsx(G,{size:12,"aria-hidden":!0})})]})]})})},t.id)})}),e.jsx(N,{open:a!==null,onOpenChange:t=>{t||s(null)},children:e.jsx(O,{side:"right",title:a!=null&&a.id?"Edit schedule":"New schedule",children:a!==null&&e.jsxs(r,{gap:4,style:{padding:"var(--space-4)"},children:[e.jsxs(r,{gap:2,children:[e.jsx("label",{htmlFor:"sched-name",style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Name"}),e.jsx(x,{id:"sched-name",value:a.name,onChange:t=>s({...a,name:t.target.value}),placeholder:"Daily digest",disabled:o})]}),e.jsxs(r,{gap:2,children:[e.jsx("label",{htmlFor:"sched-type",style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Type"}),e.jsx(m,{gap:2,children:["interval","cron","once"].map(t=>e.jsx(l,{variant:a.type===t?"primary":"ghost",size:"sm",onClick:()=>s({...a,type:t}),children:w[t]},t))})]}),e.jsxs(r,{gap:2,children:[e.jsx("label",{htmlFor:"sched-expr",style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:a.type==="interval"?"Interval (e.g. 1h, 30m)":a.type==="cron"?"Cron expr":"ISO timestamp"}),e.jsx(x,{id:"sched-expr",value:a.schedule,onChange:t=>s({...a,schedule:t.target.value}),placeholder:a.type==="interval"?"1h":a.type==="cron"?"0 9 * * *":"2026-07-14T09:00:00Z",disabled:o,"data-testid":"sched-expr"})]}),e.jsxs(r,{gap:2,children:[e.jsx("label",{htmlFor:"sched-tz",style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Timezone"}),e.jsx(x,{id:"sched-tz",value:a.timezone,onChange:t=>s({...a,timezone:t.target.value}),placeholder:"UTC",disabled:o})]}),e.jsxs(r,{gap:2,children:[e.jsx("label",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Action type"}),e.jsxs(m,{gap:2,children:[e.jsx(l,{variant:a.actionType==="agent"?"primary":"ghost",size:"sm",onClick:()=>s({...a,actionType:"agent"}),children:"Agent prompt"}),e.jsx(l,{variant:a.actionType==="command"?"primary":"ghost",size:"sm",onClick:()=>s({...a,actionType:"command"}),children:"Shell command"})]})]}),e.jsxs(r,{gap:2,children:[e.jsx("label",{htmlFor:"sched-prompt",style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:a.actionType==="agent"?"Agent prompt":"Command"}),e.jsx(L,{id:"sched-prompt",value:a.prompt,onChange:t=>s({...a,prompt:t.target.value}),placeholder:a.actionType==="agent"?"Run the daily digest report…":'echo "hello from cron"',rows:4,disabled:o})]}),S!==null&&e.jsx("div",{role:"alert",style:{padding:"var(--space-2)",background:"color-mix(in oklch, var(--danger) 12%, var(--surface-0))",border:"1px solid var(--danger)",borderRadius:"var(--radius-sm)",fontSize:"var(--fs-12)",color:"var(--danger)"},children:S}),e.jsxs(m,{gap:2,children:[e.jsx(l,{variant:"primary",onClick:()=>{F()},disabled:o||!a.name.trim()||!a.schedule.trim(),children:a!=null&&a.id?"Save":"Create"}),e.jsx(l,{variant:"ghost",onClick:()=>s(null),disabled:o,children:"Cancel"})]})]})})})]})}export{oe as SchedulesView};
|
package/bizar-dash/dist/assets/{SchedulesView-CcwDQ9Nm.js.map → SchedulesView-DY2ByBj_.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchedulesView-CcwDQ9Nm.js","sources":["../../src/web/v8/views/Schedules/SchedulesView.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\nimport { Plus, Play, Power, Trash2, RefreshCw, Clock, type LucideIcon } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Grid } from '../../ui/primitives/Grid.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Switch } from '../../ui/controls/Switch.js';\nimport { Textarea } from '../../ui/controls/Textarea.js';\nimport { Sheet, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport { useWsMessage } from '../../data/useWebSocket.js';\n\n/**\n * SchedulesView — recurring / one-time job management.\n *\n * Renders `/api/schedules` (list), lets users toggle enabled, run on\n * demand, create new schedules (interval / cron / once), and delete.\n */\n\ntype ScheduleType = 'interval' | 'cron' | 'once';\n\ninterface ScheduleAction {\n type: string;\n prompt?: string;\n agent?: string;\n command?: string;\n [key: string]: unknown;\n}\n\ninterface Schedule {\n id: string;\n name: string;\n type: ScheduleType;\n schedule: string;\n timezone: string;\n enabled: boolean;\n createdAt: string;\n updatedAt: string;\n lastRun: string | null;\n lastResult: unknown;\n lastError: unknown;\n nextRun: string | null;\n action: ScheduleAction;\n budgetCheck?: { maxConcurrent: number; skipIfBudgetLow: boolean };\n}\n\ninterface SchedulesResponse extends Array<Schedule> {}\n\ninterface CreateDraft {\n id?: string;\n name: string;\n type: ScheduleType;\n schedule: string;\n timezone: string;\n actionType: string;\n prompt: string;\n}\n\nconst TYPE_LABEL: Record<ScheduleType, string> = {\n interval: 'Interval',\n cron: 'Cron',\n once: 'One-time',\n};\n\nconst TYPE_ICON: Record<ScheduleType, LucideIcon> = {\n interval: RefreshCw,\n cron: Clock,\n once: Play,\n};\n\nfunction StatusBadge({ sched }: { sched: Schedule }): JSX.Element {\n if (!sched.enabled) return <Badge tone=\"neutral\">disabled</Badge>;\n if (sched.lastError) return <Badge tone=\"danger\">error</Badge>;\n if (sched.lastRun === null) return <Badge tone=\"info\">never run</Badge>;\n return <Badge tone=\"success\">active</Badge>;\n}\n\nfunction Box(props: { children?: React.ReactNode; style?: React.CSSProperties }): JSX.Element {\n return <div style={props.style}>{props.children}</div>;\n}\n\nexport function SchedulesView(): JSX.Element {\n const res = useFetch<SchedulesResponse>('/api/schedules');\n const [live, setLive] = useState<Schedule[]>([]);\n const [draft, setDraft] = useState<CreateDraft | null>(null);\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n\n useWsMessage('schedules:change', useCallback(() => { void res.refetch(); }, [res]));\n\n const schedules = useMemo<Schedule[]>(() => [...live, ...(res.data || [])], [live, res.data]);\n\n const refresh = (): void => { void res.refetch(); };\n\n const toggleEnabled = async (s: Schedule): Promise<void> => {\n setActionError(null);\n try {\n await fetchJson(`/api/schedules/${encodeURIComponent(s.id)}`, {\n method: 'PATCH',\n body: { enabled: !s.enabled },\n });\n refresh();\n } catch (err) {\n setActionError(err instanceof FetchError ? err.message : String(err));\n }\n };\n\n const runNow = async (s: Schedule): Promise<void> => {\n setActionError(null);\n setBusy(true);\n try {\n await fetchJson(`/api/schedules/${encodeURIComponent(s.id)}/run`, { method: 'POST' });\n refresh();\n } catch (err) {\n setActionError(err instanceof FetchError ? err.message : String(err));\n } finally {\n setBusy(false);\n }\n };\n\n const deleteSchedule = async (id: string): Promise<void> => {\n setActionError(null);\n setBusy(true);\n try {\n await fetchJson(`/api/schedules/${encodeURIComponent(id)}`, { method: 'DELETE' });\n refresh();\n } catch (err) {\n setActionError(err instanceof FetchError ? err.message : String(err));\n } finally {\n setBusy(false);\n }\n };\n\n const createSchedule = async (): Promise<void> => {\n if (!draft || !draft.name.trim() || !draft.schedule.trim()) return;\n setBusy(true);\n setError(null);\n try {\n const action: ScheduleAction = { type: draft.actionType };\n if (draft.actionType === 'agent') action.prompt = draft.prompt;\n if (draft.actionType === 'command') action.command = draft.prompt;\n if (draft.id) {\n // Edit path — PATCH the existing schedule.\n await fetchJson(`/api/schedules/${encodeURIComponent(draft.id)}`, {\n method: 'PATCH',\n body: {\n name: draft.name,\n type: draft.type,\n schedule: draft.schedule,\n timezone: draft.timezone || 'UTC',\n action,\n },\n });\n } else {\n await fetchJson('/api/schedules', {\n method: 'POST',\n body: {\n name: draft.name,\n type: draft.type,\n schedule: draft.schedule,\n timezone: draft.timezone || 'UTC',\n action,\n enabled: true,\n },\n });\n }\n setDraft(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : String(err));\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={5} data-testid=\"schedules-view\">\n <ViewHeader\n title=\"Schedules\"\n description=\"Recurring and one-time jobs. Toggle enabled, run on demand, or create new.\"\n actions={\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={() => setDraft({ name: '', type: 'interval', schedule: '1h', timezone: 'UTC', actionType: 'agent', prompt: '' })}\n data-testid=\"schedules-new\"\n >\n <Plus size={14} aria-hidden /> New schedule\n </Button>\n }\n />\n\n {actionError !== null && (\n <div role=\"alert\" style={{ padding: 'var(--space-2) var(--space-3)', background: 'color-mix(in oklch, var(--danger) 12%, var(--surface-0))', border: '1px solid var(--danger)', borderRadius: 'var(--radius-md)', fontSize: 'var(--fs-12)', color: 'var(--danger)' }}>\n {actionError}\n </div>\n )}\n\n {res.loading && schedules.length === 0 ? (\n <Skeleton style={{ height: 240 }} />\n ) : schedules.length === 0 ? (\n <Card>\n <CardBody>\n <Stack gap={1} align=\"center\">\n <Clock size={32} aria-hidden style={{ color: 'var(--fg-muted)' }} />\n <strong>No schedules yet</strong>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-13)' }}>\n Create one with the button above.\n </span>\n </Stack>\n </CardBody>\n </Card>\n ) : (\n <Stack gap={3}>\n {schedules.map((s) => {\n const TypeIcon = TYPE_ICON[s.type] ?? Clock;\n return (\n <Card key={s.id} data-testid={`schedule-${s.id}`}>\n <CardBody>\n <Grid cols={4} gap={3} style={{ alignItems: 'center' }}>\n <Stack gap={1}>\n <Inline align=\"center\" gap={2}>\n <TypeIcon size={12} aria-hidden style={{ color: 'var(--fg-muted)' }} />\n <strong style={{ fontSize: 'var(--fs-14)' }}>{s.name}</strong>\n </Inline>\n <Inline gap={2}>\n <Badge tone=\"neutral\">{TYPE_LABEL[s.type]}</Badge>\n <StatusBadge sched={s} />\n </Inline>\n </Stack>\n\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Schedule</span>\n <code style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>{s.schedule}</code>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{s.timezone}</span>\n </Stack>\n\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Next run</span>\n {s.nextRun ? (\n <code style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>\n {new Date(s.nextRun).toLocaleString()}\n </code>\n ) : (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>—</span>\n )}\n {s.lastRun && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n Last: {new Date(s.lastRun).toLocaleDateString()}\n </span>\n )}\n </Stack>\n\n <Inline align=\"center\" gap={2} justify=\"end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setDraft({\n id: s.id,\n name: s.name,\n type: s.type,\n schedule: s.schedule,\n timezone: s.timezone || 'UTC',\n actionType: 'agent',\n prompt: (s.action && (s.action as { prompt?: string }).prompt) || '',\n })}\n data-testid={`schedule-edit-${s.id}`}\n title=\"Edit\"\n >\n Edit\n </Button>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => { void runNow(s); }}\n disabled={busy}\n data-testid={`schedule-run-${s.id}`}\n title=\"Run now\"\n >\n <Play size={12} aria-hidden />\n </Button>\n <Switch\n checked={s.enabled}\n onCheckedChange={() => { void toggleEnabled(s); }}\n aria-label={`Toggle ${s.name} enabled`}\n />\n <Button\n variant=\"danger\"\n size=\"sm\"\n onClick={() => { void deleteSchedule(s.id); }}\n disabled={busy}\n data-testid={`schedule-delete-${s.id}`}\n title=\"Delete\"\n >\n <Trash2 size={12} aria-hidden />\n </Button>\n </Inline>\n </Grid>\n </CardBody>\n </Card>\n );\n })}\n </Stack>\n )}\n\n <Sheet open={draft !== null} onOpenChange={(o) => { if (!o) setDraft(null); }}>\n <SheetContent side=\"right\" title={draft?.id ? 'Edit schedule' : 'New schedule'}>\n {draft !== null && (\n <Stack gap={4} style={{ padding: 'var(--space-4)' }}>\n <Stack gap={2}>\n <label htmlFor=\"sched-name\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Name</label>\n <Input\n id=\"sched-name\"\n value={draft.name}\n onChange={(e) => setDraft({ ...draft, name: e.target.value })}\n placeholder=\"Daily digest\"\n disabled={busy}\n />\n </Stack>\n\n <Stack gap={2}>\n <label htmlFor=\"sched-type\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Type</label>\n <Inline gap={2}>\n {(['interval', 'cron', 'once'] as const).map((t) => (\n <Button\n key={t}\n variant={draft.type === t ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => setDraft({ ...draft, type: t })}\n >\n {TYPE_LABEL[t]}\n </Button>\n ))}\n </Inline>\n </Stack>\n\n <Stack gap={2}>\n <label htmlFor=\"sched-expr\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {draft.type === 'interval' ? 'Interval (e.g. 1h, 30m)' : draft.type === 'cron' ? 'Cron expr' : 'ISO timestamp'}\n </label>\n <Input\n id=\"sched-expr\"\n value={draft.schedule}\n onChange={(e) => setDraft({ ...draft, schedule: e.target.value })}\n placeholder={draft.type === 'interval' ? '1h' : draft.type === 'cron' ? '0 9 * * *' : '2026-07-14T09:00:00Z'}\n disabled={busy}\n data-testid=\"sched-expr\"\n />\n </Stack>\n\n <Stack gap={2}>\n <label htmlFor=\"sched-tz\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Timezone</label>\n <Input\n id=\"sched-tz\"\n value={draft.timezone}\n onChange={(e) => setDraft({ ...draft, timezone: e.target.value })}\n placeholder=\"UTC\"\n disabled={busy}\n />\n </Stack>\n\n <Stack gap={2}>\n <label style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Action type</label>\n <Inline gap={2}>\n <Button\n variant={draft.actionType === 'agent' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => setDraft({ ...draft, actionType: 'agent' })}\n >\n Agent prompt\n </Button>\n <Button\n variant={draft.actionType === 'command' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => setDraft({ ...draft, actionType: 'command' })}\n >\n Shell command\n </Button>\n </Inline>\n </Stack>\n\n <Stack gap={2}>\n <label htmlFor=\"sched-prompt\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {draft.actionType === 'agent' ? 'Agent prompt' : 'Command'}\n </label>\n <Textarea\n id=\"sched-prompt\"\n value={draft.prompt}\n onChange={(e) => setDraft({ ...draft, prompt: e.target.value })}\n placeholder={draft.actionType === 'agent' ? 'Run the daily digest report…' : 'echo \"hello from cron\"'}\n rows={4}\n disabled={busy}\n />\n </Stack>\n\n {error !== null && (\n <div role=\"alert\" style={{ padding: 'var(--space-2)', background: 'color-mix(in oklch, var(--danger) 12%, var(--surface-0))', border: '1px solid var(--danger)', borderRadius: 'var(--radius-sm)', fontSize: 'var(--fs-12)', color: 'var(--danger)' }}>\n {error}\n </div>\n )}\n\n <Inline gap={2}>\n <Button\n variant=\"primary\"\n onClick={() => { void createSchedule(); }}\n disabled={busy || !draft.name.trim() || !draft.schedule.trim()}\n >\n {draft?.id ? 'Save' : 'Create'}\n </Button>\n <Button variant=\"ghost\" onClick={() => setDraft(null)} disabled={busy}>\n Cancel\n </Button>\n </Inline>\n </Stack>\n )}\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n"],"names":["TYPE_LABEL","TYPE_ICON","RefreshCw","Clock","Play","StatusBadge","sched","Badge","jsx","SchedulesView","res","useFetch","live","setLive","useState","draft","setDraft","busy","setBusy","error","setError","actionError","setActionError","useWsMessage","useCallback","schedules","useMemo","refresh","toggleEnabled","s","fetchJson","err","FetchError","runNow","deleteSchedule","id","createSchedule","action","jsxs","Stack","ViewHeader","Button","Plus","Skeleton","Card","CardBody","TypeIcon","Grid","Inline","Switch","Trash2","Sheet","o","SheetContent","Input","e","Textarea"],"mappings":"mqBAgEA,MAAMA,EAA2C,CAC/C,SAAU,WACV,KAAM,OACN,KAAM,UACR,EAEMC,EAA8C,CAClD,SAAUC,EACV,KAAMC,EACN,KAAMC,CACR,EAEA,SAASC,EAAY,CAAE,MAAAC,GAA2C,CAChE,OAAKA,EAAM,QACPA,EAAM,gBAAmBC,EAAA,CAAM,KAAK,SAAS,SAAA,QAAK,EAClDD,EAAM,UAAY,WAAcC,EAAA,CAAM,KAAK,OAAO,SAAA,WAAA,CAAS,EACxDC,EAAAA,IAACD,EAAA,CAAM,KAAK,UAAU,SAAA,SAAM,QAHPA,EAAA,CAAM,KAAK,UAAU,SAAA,WAAQ,CAI3D,CAMO,SAASE,IAA6B,CAC3C,MAAMC,EAAMC,EAA4B,gBAAgB,EAClD,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAqB,CAAA,CAAE,EACzC,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAA6B,IAAI,EACrD,CAACG,EAAMC,CAAO,EAAIJ,EAAAA,SAAkB,EAAK,EACzC,CAACK,EAAOC,CAAQ,EAAIN,EAAAA,SAAwB,IAAI,EAChD,CAACO,EAAaC,CAAc,EAAIR,EAAAA,SAAwB,IAAI,EAElES,EAAa,mBAAoBC,EAAAA,YAAY,IAAM,CAAOd,EAAI,QAAA,CAAW,EAAG,CAACA,CAAG,CAAC,CAAC,EAElF,MAAMe,EAAYC,EAAAA,QAAoB,IAAM,CAAC,GAAGd,EAAM,GAAIF,EAAI,MAAQ,CAAA,CAAG,EAAG,CAACE,EAAMF,EAAI,IAAI,CAAC,EAEtFiB,EAAU,IAAY,CAAOjB,EAAI,QAAA,CAAW,EAE5CkB,EAAgB,MAAOC,GAA+B,CAC1DP,EAAe,IAAI,EACnB,GAAI,CACF,MAAMQ,EAAU,kBAAkB,mBAAmBD,EAAE,EAAE,CAAC,GAAI,CAC5D,OAAQ,QACR,KAAM,CAAE,QAAS,CAACA,EAAE,OAAA,CAAQ,CAC7B,EACDF,EAAA,CACF,OAASI,EAAK,CACZT,EAAeS,aAAeC,EAAaD,EAAI,QAAU,OAAOA,CAAG,CAAC,CACtE,CACF,EAEME,EAAS,MAAOJ,GAA+B,CACnDP,EAAe,IAAI,EACnBJ,EAAQ,EAAI,EACZ,GAAI,CACF,MAAMY,EAAU,kBAAkB,mBAAmBD,EAAE,EAAE,CAAC,OAAQ,CAAE,OAAQ,MAAA,CAAQ,EACpFF,EAAA,CACF,OAASI,EAAK,CACZT,EAAeS,aAAeC,EAAaD,EAAI,QAAU,OAAOA,CAAG,CAAC,CACtE,QAAA,CACEb,EAAQ,EAAK,CACf,CACF,EAEMgB,EAAiB,MAAOC,GAA8B,CAC1Db,EAAe,IAAI,EACnBJ,EAAQ,EAAI,EACZ,GAAI,CACF,MAAMY,EAAU,kBAAkB,mBAAmBK,CAAE,CAAC,GAAI,CAAE,OAAQ,SAAU,EAChFR,EAAA,CACF,OAASI,EAAK,CACZT,EAAeS,aAAeC,EAAaD,EAAI,QAAU,OAAOA,CAAG,CAAC,CACtE,QAAA,CACEb,EAAQ,EAAK,CACf,CACF,EAEMkB,EAAiB,SAA2B,CAChD,GAAI,GAACrB,GAAS,CAACA,EAAM,KAAK,KAAA,GAAU,CAACA,EAAM,SAAS,QACpD,CAAAG,EAAQ,EAAI,EACZE,EAAS,IAAI,EACb,GAAI,CACF,MAAMiB,EAAyB,CAAE,KAAMtB,EAAM,UAAA,EACzCA,EAAM,aAAe,UAASsB,EAAO,OAAStB,EAAM,QACpDA,EAAM,aAAe,YAAWsB,EAAO,QAAUtB,EAAM,QACvDA,EAAM,GAER,MAAMe,EAAU,kBAAkB,mBAAmBf,EAAM,EAAE,CAAC,GAAI,CAChE,OAAQ,QACR,KAAM,CACJ,KAAMA,EAAM,KACZ,KAAMA,EAAM,KACZ,SAAUA,EAAM,SAChB,SAAUA,EAAM,UAAY,MAC5B,OAAAsB,CAAA,CACF,CACD,EAED,MAAMP,EAAU,iBAAkB,CAChC,OAAQ,OACR,KAAM,CACJ,KAAMf,EAAM,KACZ,KAAMA,EAAM,KACZ,SAAUA,EAAM,SAChB,SAAUA,EAAM,UAAY,MAC5B,OAAAsB,EACA,QAAS,EAAA,CACX,CACD,EAEHrB,EAAS,IAAI,EACbW,EAAA,CACF,OAASI,EAAK,CACZX,EAASW,aAAeC,EAAaD,EAAI,QAAU,OAAOA,CAAG,CAAC,CAChE,QAAA,CACEb,EAAQ,EAAK,CACf,EACF,EAEA,OACEoB,EAAAA,KAACC,EAAA,CAAM,IAAK,EAAG,cAAY,iBACzB,SAAA,CAAA/B,EAAAA,IAACgC,EAAA,CACC,MAAM,YACN,YAAY,6EACZ,QACEF,EAAAA,KAACG,EAAA,CACC,QAAQ,UACR,KAAK,KACL,QAAS,IAAMzB,EAAS,CAAE,KAAM,GAAI,KAAM,WAAY,SAAU,KAAM,SAAU,MAAO,WAAY,QAAS,OAAQ,GAAI,EACxH,cAAY,gBAEZ,SAAA,CAAAR,EAAAA,IAACkC,EAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAAE,eAAA,CAAA,CAAA,CAChC,CAAA,EAIHrB,IAAgB,MACfb,MAAC,MAAA,CAAI,KAAK,QAAQ,MAAO,CAAE,QAAS,gCAAiC,WAAY,2DAA4D,OAAQ,0BAA2B,aAAc,mBAAoB,SAAU,eAAgB,MAAO,eAAA,EAChP,SAAAa,CAAA,CACH,EAGDX,EAAI,SAAWe,EAAU,SAAW,QAClCkB,EAAA,CAAS,MAAO,CAAE,OAAQ,GAAA,CAAI,CAAG,EAChClB,EAAU,SAAW,EACvBjB,EAAAA,IAACoC,EAAA,CACC,SAAApC,EAAAA,IAACqC,EAAA,CACC,SAAAP,EAAAA,KAACC,EAAA,CAAM,IAAK,EAAG,MAAM,SACnB,SAAA,CAAA/B,EAAAA,IAACL,EAAA,CAAM,KAAM,GAAI,cAAW,GAAC,MAAO,CAAE,MAAO,iBAAA,CAAkB,CAAG,EAClEK,EAAAA,IAAC,UAAO,SAAA,kBAAA,CAAgB,EACxBA,EAAAA,IAAC,QAAK,MAAO,CAAE,MAAO,kBAAmB,SAAU,cAAA,EAAkB,SAAA,mCAAA,CAErE,CAAA,CAAA,CACF,CAAA,CACF,CAAA,CACF,EAEAA,EAAAA,IAAC+B,EAAA,CAAM,IAAK,EACT,SAAAd,EAAU,IAAKI,GAAM,CACpB,MAAMiB,EAAW7C,EAAU4B,EAAE,IAAI,GAAK1B,EACtC,aACGyC,EAAA,CAAgB,cAAa,YAAYf,EAAE,EAAE,GAC5C,SAAArB,EAAAA,IAACqC,EAAA,CACC,gBAACE,EAAA,CAAK,KAAM,EAAG,IAAK,EAAG,MAAO,CAAE,WAAY,UAC1C,SAAA,CAAAT,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAD,EAAAA,KAACU,EAAA,CAAO,MAAM,SAAS,IAAK,EAC1B,SAAA,CAAAxC,EAAAA,IAACsC,EAAA,CAAS,KAAM,GAAI,cAAW,GAAC,MAAO,CAAE,MAAO,iBAAA,CAAkB,CAAG,EACrEtC,MAAC,UAAO,MAAO,CAAE,SAAU,gBAAmB,WAAE,IAAA,CAAK,CAAA,EACvD,EACA8B,EAAAA,KAACU,EAAA,CAAO,IAAK,EACX,SAAA,CAAAxC,MAACD,GAAM,KAAK,UAAW,SAAAP,EAAW6B,EAAE,IAAI,EAAE,EAC1CrB,EAAAA,IAACH,EAAA,CAAY,MAAOwB,CAAA,CAAG,CAAA,CAAA,CACzB,CAAA,EACF,EAEAS,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAA/B,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,UAAA,CAAQ,EAC7EA,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,WAAY,mBAAoB,SAAU,cAAA,EAAmB,SAAAqB,EAAE,QAAA,CAAS,EACvFrB,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAsB,SAAAqB,EAAE,QAAA,CAAS,CAAA,EACnF,EAEAS,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAA/B,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,UAAA,CAAQ,EAC5EqB,EAAE,QACDrB,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,WAAY,mBAAoB,SAAU,cAAA,EACtD,SAAA,IAAI,KAAKqB,EAAE,OAAO,EAAE,eAAA,CAAe,CACtC,EAEArB,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,GAAA,CAAC,EAEvEqB,EAAE,SACDS,OAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,CAAA,SAC5D,IAAI,KAAKT,EAAE,OAAO,EAAE,mBAAA,CAAmB,CAAA,CAChD,CAAA,EAEJ,SAECmB,EAAA,CAAO,MAAM,SAAS,IAAK,EAAG,QAAQ,MACrC,SAAA,CAAAxC,EAAAA,IAACiC,EAAA,CACC,QAAQ,QACR,KAAK,KACL,QAAS,IAAMzB,EAAS,CACtB,GAAIa,EAAE,GACN,KAAMA,EAAE,KACR,KAAMA,EAAE,KACR,SAAUA,EAAE,SACZ,SAAUA,EAAE,UAAY,MACxB,WAAY,QACZ,OAASA,EAAE,QAAWA,EAAE,OAA+B,QAAW,EAAA,CACnE,EACD,cAAa,iBAAiBA,EAAE,EAAE,GAClC,MAAM,OACP,SAAA,MAAA,CAAA,EAGDrB,EAAAA,IAACiC,EAAA,CACC,QAAQ,YACR,KAAK,KACL,QAAS,IAAM,CAAOR,EAAOJ,CAAC,CAAG,EACjC,SAAUZ,EACV,cAAa,gBAAgBY,EAAE,EAAE,GACjC,MAAM,UAEN,SAAArB,EAAAA,IAACJ,EAAA,CAAK,KAAM,GAAI,cAAW,EAAA,CAAC,CAAA,CAAA,EAE9BI,EAAAA,IAACyC,EAAA,CACC,QAASpB,EAAE,QACX,gBAAiB,IAAM,CAAOD,EAAcC,CAAC,CAAG,EAChD,aAAY,UAAUA,EAAE,IAAI,UAAA,CAAA,EAE9BrB,EAAAA,IAACiC,EAAA,CACC,QAAQ,SACR,KAAK,KACL,QAAS,IAAM,CAAOP,EAAeL,EAAE,EAAE,CAAG,EAC5C,SAAUZ,EACV,cAAa,mBAAmBY,EAAE,EAAE,GACpC,MAAM,SAEN,SAAArB,EAAAA,IAAC0C,EAAA,CAAO,KAAM,GAAI,cAAW,EAAA,CAAC,CAAA,CAAA,CAChC,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,GAjFSrB,EAAE,EAkFb,CAEJ,CAAC,CAAA,CACH,QAGDsB,EAAA,CAAM,KAAMpC,IAAU,KAAM,aAAeqC,GAAM,CAAOA,GAAGpC,EAAS,IAAI,CAAG,EAC1E,eAACqC,EAAA,CAAa,KAAK,QAAQ,MAAOtC,GAAA,MAAAA,EAAO,GAAK,gBAAkB,eAC7D,aAAU,MACTuB,OAACC,GAAM,IAAK,EAAG,MAAO,CAAE,QAAS,kBAC/B,SAAA,CAAAD,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAA/B,EAAAA,IAAC,QAAA,CAAM,QAAQ,aAAa,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,MAAA,CAAI,EAC/FA,EAAAA,IAAC8C,EAAA,CACC,GAAG,aACH,MAAOvC,EAAM,KACb,SAAWwC,GAAMvC,EAAS,CAAE,GAAGD,EAAO,KAAMwC,EAAE,OAAO,MAAO,EAC5D,YAAY,eACZ,SAAUtC,CAAA,CAAA,CACZ,EACF,EAEAqB,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAA/B,EAAAA,IAAC,QAAA,CAAM,QAAQ,aAAa,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,MAAA,CAAI,EAC/FA,EAAAA,IAACwC,EAAA,CAAO,IAAK,EACT,SAAA,CAAC,WAAY,OAAQ,MAAM,EAAY,IAAK,GAC5CxC,EAAAA,IAACiC,EAAA,CAEC,QAAS1B,EAAM,OAAS,EAAI,UAAY,QACxC,KAAK,KACL,QAAS,IAAMC,EAAS,CAAE,GAAGD,EAAO,KAAM,EAAG,EAE5C,WAAW,CAAC,CAAA,EALR,CAAA,CAOR,CAAA,CACH,CAAA,EACF,EAEAuB,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAA/B,MAAC,SAAM,QAAQ,aAAa,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EACnE,SAAAO,EAAM,OAAS,WAAa,0BAA4BA,EAAM,OAAS,OAAS,YAAc,gBACjG,EACAP,EAAAA,IAAC8C,EAAA,CACC,GAAG,aACH,MAAOvC,EAAM,SACb,SAAWwC,GAAMvC,EAAS,CAAE,GAAGD,EAAO,SAAUwC,EAAE,OAAO,MAAO,EAChE,YAAaxC,EAAM,OAAS,WAAa,KAAOA,EAAM,OAAS,OAAS,YAAc,uBACtF,SAAUE,EACV,cAAY,YAAA,CAAA,CACd,EACF,EAEAqB,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAA/B,EAAAA,IAAC,QAAA,CAAM,QAAQ,WAAW,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,UAAA,CAAQ,EACjGA,EAAAA,IAAC8C,EAAA,CACC,GAAG,WACH,MAAOvC,EAAM,SACb,SAAWwC,GAAMvC,EAAS,CAAE,GAAGD,EAAO,SAAUwC,EAAE,OAAO,MAAO,EAChE,YAAY,MACZ,SAAUtC,CAAA,CAAA,CACZ,EACF,EAEAqB,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAA/B,EAAAA,IAAC,QAAA,CAAM,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,aAAA,CAAW,EACjF8B,EAAAA,KAACU,EAAA,CAAO,IAAK,EACX,SAAA,CAAAxC,EAAAA,IAACiC,EAAA,CACC,QAAS1B,EAAM,aAAe,QAAU,UAAY,QACpD,KAAK,KACL,QAAS,IAAMC,EAAS,CAAE,GAAGD,EAAO,WAAY,QAAS,EAC1D,SAAA,cAAA,CAAA,EAGDP,EAAAA,IAACiC,EAAA,CACC,QAAS1B,EAAM,aAAe,UAAY,UAAY,QACtD,KAAK,KACL,QAAS,IAAMC,EAAS,CAAE,GAAGD,EAAO,WAAY,UAAW,EAC5D,SAAA,eAAA,CAAA,CAED,CAAA,CACF,CAAA,EACF,EAEAuB,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAA/B,EAAAA,IAAC,QAAA,CAAM,QAAQ,eAAe,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EACrE,SAAAO,EAAM,aAAe,QAAU,eAAiB,UACnD,EACAP,EAAAA,IAACgD,EAAA,CACC,GAAG,eACH,MAAOzC,EAAM,OACb,SAAWwC,GAAMvC,EAAS,CAAE,GAAGD,EAAO,OAAQwC,EAAE,OAAO,MAAO,EAC9D,YAAaxC,EAAM,aAAe,QAAU,+BAAiC,yBAC7E,KAAM,EACN,SAAUE,CAAA,CAAA,CACZ,EACF,EAECE,IAAU,MACTX,MAAC,MAAA,CAAI,KAAK,QAAQ,MAAO,CAAE,QAAS,iBAAkB,WAAY,2DAA4D,OAAQ,0BAA2B,aAAc,mBAAoB,SAAU,eAAgB,MAAO,eAAA,EACjO,SAAAW,CAAA,CACH,EAGFmB,EAAAA,KAACU,EAAA,CAAO,IAAK,EACX,SAAA,CAAAxC,EAAAA,IAACiC,EAAA,CACC,QAAQ,UACR,QAAS,IAAM,CAAOL,EAAA,CAAkB,EACxC,SAAUnB,GAAQ,CAACF,EAAM,KAAK,QAAU,CAACA,EAAM,SAAS,KAAA,EAEvD,SAAAA,GAAA,MAAAA,EAAO,GAAK,OAAS,QAAA,CAAA,EAExBP,EAAAA,IAACiC,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAMzB,EAAS,IAAI,EAAG,SAAUC,EAAM,SAAA,QAAA,CAEvE,CAAA,CAAA,CACF,CAAA,CAAA,CACF,EAEJ,CAAA,CACF,CAAA,EACF,CAEJ"}
|
|
1
|
+
{"version":3,"file":"SchedulesView-DY2ByBj_.js","sources":["../../src/web/v8/views/Schedules/SchedulesView.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\nimport { Plus, Play, Power, Trash2, RefreshCw, Clock, type LucideIcon } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Grid } from '../../ui/primitives/Grid.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Switch } from '../../ui/controls/Switch.js';\nimport { Textarea } from '../../ui/controls/Textarea.js';\nimport { Sheet, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport { useWsMessage } from '../../data/useWebSocket.js';\n\n/**\n * SchedulesView — recurring / one-time job management.\n *\n * Renders `/api/schedules` (list), lets users toggle enabled, run on\n * demand, create new schedules (interval / cron / once), and delete.\n */\n\ntype ScheduleType = 'interval' | 'cron' | 'once';\n\ninterface ScheduleAction {\n type: string;\n prompt?: string;\n agent?: string;\n command?: string;\n [key: string]: unknown;\n}\n\ninterface Schedule {\n id: string;\n name: string;\n type: ScheduleType;\n schedule: string;\n timezone: string;\n enabled: boolean;\n createdAt: string;\n updatedAt: string;\n lastRun: string | null;\n lastResult: unknown;\n lastError: unknown;\n nextRun: string | null;\n action: ScheduleAction;\n budgetCheck?: { maxConcurrent: number; skipIfBudgetLow: boolean };\n}\n\ninterface SchedulesResponse extends Array<Schedule> {}\n\ninterface CreateDraft {\n id?: string;\n name: string;\n type: ScheduleType;\n schedule: string;\n timezone: string;\n actionType: string;\n prompt: string;\n}\n\nconst TYPE_LABEL: Record<ScheduleType, string> = {\n interval: 'Interval',\n cron: 'Cron',\n once: 'One-time',\n};\n\nconst TYPE_ICON: Record<ScheduleType, LucideIcon> = {\n interval: RefreshCw,\n cron: Clock,\n once: Play,\n};\n\nfunction StatusBadge({ sched }: { sched: Schedule }): JSX.Element {\n if (!sched.enabled) return <Badge tone=\"neutral\">disabled</Badge>;\n if (sched.lastError) return <Badge tone=\"danger\">error</Badge>;\n if (sched.lastRun === null) return <Badge tone=\"info\">never run</Badge>;\n return <Badge tone=\"success\">active</Badge>;\n}\n\nfunction Box(props: { children?: React.ReactNode; style?: React.CSSProperties }): JSX.Element {\n return <div style={props.style}>{props.children}</div>;\n}\n\nexport function SchedulesView(): JSX.Element {\n const res = useFetch<SchedulesResponse>('/api/schedules');\n const [live, setLive] = useState<Schedule[]>([]);\n const [draft, setDraft] = useState<CreateDraft | null>(null);\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n\n useWsMessage('schedules:change', useCallback(() => { void res.refetch(); }, [res]));\n\n const schedules = useMemo<Schedule[]>(() => [...live, ...(res.data || [])], [live, res.data]);\n\n const refresh = (): void => { void res.refetch(); };\n\n const toggleEnabled = async (s: Schedule): Promise<void> => {\n setActionError(null);\n try {\n await fetchJson(`/api/schedules/${encodeURIComponent(s.id)}`, {\n method: 'PATCH',\n body: { enabled: !s.enabled },\n });\n refresh();\n } catch (err) {\n setActionError(err instanceof FetchError ? err.message : String(err));\n }\n };\n\n const runNow = async (s: Schedule): Promise<void> => {\n setActionError(null);\n setBusy(true);\n try {\n await fetchJson(`/api/schedules/${encodeURIComponent(s.id)}/run`, { method: 'POST' });\n refresh();\n } catch (err) {\n setActionError(err instanceof FetchError ? err.message : String(err));\n } finally {\n setBusy(false);\n }\n };\n\n const deleteSchedule = async (id: string): Promise<void> => {\n setActionError(null);\n setBusy(true);\n try {\n await fetchJson(`/api/schedules/${encodeURIComponent(id)}`, { method: 'DELETE' });\n refresh();\n } catch (err) {\n setActionError(err instanceof FetchError ? err.message : String(err));\n } finally {\n setBusy(false);\n }\n };\n\n const createSchedule = async (): Promise<void> => {\n if (!draft || !draft.name.trim() || !draft.schedule.trim()) return;\n setBusy(true);\n setError(null);\n try {\n const action: ScheduleAction = { type: draft.actionType };\n if (draft.actionType === 'agent') action.prompt = draft.prompt;\n if (draft.actionType === 'command') action.command = draft.prompt;\n if (draft.id) {\n // Edit path — PATCH the existing schedule.\n await fetchJson(`/api/schedules/${encodeURIComponent(draft.id)}`, {\n method: 'PATCH',\n body: {\n name: draft.name,\n type: draft.type,\n schedule: draft.schedule,\n timezone: draft.timezone || 'UTC',\n action,\n },\n });\n } else {\n await fetchJson('/api/schedules', {\n method: 'POST',\n body: {\n name: draft.name,\n type: draft.type,\n schedule: draft.schedule,\n timezone: draft.timezone || 'UTC',\n action,\n enabled: true,\n },\n });\n }\n setDraft(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : String(err));\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={5} data-testid=\"schedules-view\">\n <ViewHeader\n title=\"Schedules\"\n description=\"Recurring and one-time jobs. Toggle enabled, run on demand, or create new.\"\n actions={\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={() => setDraft({ name: '', type: 'interval', schedule: '1h', timezone: 'UTC', actionType: 'agent', prompt: '' })}\n data-testid=\"schedules-new\"\n >\n <Plus size={14} aria-hidden /> New schedule\n </Button>\n }\n />\n\n {actionError !== null && (\n <div role=\"alert\" style={{ padding: 'var(--space-2) var(--space-3)', background: 'color-mix(in oklch, var(--danger) 12%, var(--surface-0))', border: '1px solid var(--danger)', borderRadius: 'var(--radius-md)', fontSize: 'var(--fs-12)', color: 'var(--danger)' }}>\n {actionError}\n </div>\n )}\n\n {res.loading && schedules.length === 0 ? (\n <Skeleton style={{ height: 240 }} />\n ) : schedules.length === 0 ? (\n <Card>\n <CardBody>\n <Stack gap={1} align=\"center\">\n <Clock size={32} aria-hidden style={{ color: 'var(--fg-muted)' }} />\n <strong>No schedules yet</strong>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-13)' }}>\n Create one with the button above.\n </span>\n </Stack>\n </CardBody>\n </Card>\n ) : (\n <Stack gap={3}>\n {schedules.map((s) => {\n const TypeIcon = TYPE_ICON[s.type] ?? Clock;\n return (\n <Card key={s.id} data-testid={`schedule-${s.id}`}>\n <CardBody>\n <Grid cols={4} gap={3} style={{ alignItems: 'center' }}>\n <Stack gap={1}>\n <Inline align=\"center\" gap={2}>\n <TypeIcon size={12} aria-hidden style={{ color: 'var(--fg-muted)' }} />\n <strong style={{ fontSize: 'var(--fs-14)' }}>{s.name}</strong>\n </Inline>\n <Inline gap={2}>\n <Badge tone=\"neutral\">{TYPE_LABEL[s.type]}</Badge>\n <StatusBadge sched={s} />\n </Inline>\n </Stack>\n\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Schedule</span>\n <code style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>{s.schedule}</code>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{s.timezone}</span>\n </Stack>\n\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Next run</span>\n {s.nextRun ? (\n <code style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-12)' }}>\n {new Date(s.nextRun).toLocaleString()}\n </code>\n ) : (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>—</span>\n )}\n {s.lastRun && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n Last: {new Date(s.lastRun).toLocaleDateString()}\n </span>\n )}\n </Stack>\n\n <Inline align=\"center\" gap={2} justify=\"end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setDraft({\n id: s.id,\n name: s.name,\n type: s.type,\n schedule: s.schedule,\n timezone: s.timezone || 'UTC',\n actionType: 'agent',\n prompt: (s.action && (s.action as { prompt?: string }).prompt) || '',\n })}\n data-testid={`schedule-edit-${s.id}`}\n title=\"Edit\"\n >\n Edit\n </Button>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => { void runNow(s); }}\n disabled={busy}\n data-testid={`schedule-run-${s.id}`}\n title=\"Run now\"\n >\n <Play size={12} aria-hidden />\n </Button>\n <Switch\n checked={s.enabled}\n onCheckedChange={() => { void toggleEnabled(s); }}\n aria-label={`Toggle ${s.name} enabled`}\n />\n <Button\n variant=\"danger\"\n size=\"sm\"\n onClick={() => { void deleteSchedule(s.id); }}\n disabled={busy}\n data-testid={`schedule-delete-${s.id}`}\n title=\"Delete\"\n >\n <Trash2 size={12} aria-hidden />\n </Button>\n </Inline>\n </Grid>\n </CardBody>\n </Card>\n );\n })}\n </Stack>\n )}\n\n <Sheet open={draft !== null} onOpenChange={(o) => { if (!o) setDraft(null); }}>\n <SheetContent side=\"right\" title={draft?.id ? 'Edit schedule' : 'New schedule'}>\n {draft !== null && (\n <Stack gap={4} style={{ padding: 'var(--space-4)' }}>\n <Stack gap={2}>\n <label htmlFor=\"sched-name\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Name</label>\n <Input\n id=\"sched-name\"\n value={draft.name}\n onChange={(e) => setDraft({ ...draft, name: e.target.value })}\n placeholder=\"Daily digest\"\n disabled={busy}\n />\n </Stack>\n\n <Stack gap={2}>\n <label htmlFor=\"sched-type\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Type</label>\n <Inline gap={2}>\n {(['interval', 'cron', 'once'] as const).map((t) => (\n <Button\n key={t}\n variant={draft.type === t ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => setDraft({ ...draft, type: t })}\n >\n {TYPE_LABEL[t]}\n </Button>\n ))}\n </Inline>\n </Stack>\n\n <Stack gap={2}>\n <label htmlFor=\"sched-expr\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {draft.type === 'interval' ? 'Interval (e.g. 1h, 30m)' : draft.type === 'cron' ? 'Cron expr' : 'ISO timestamp'}\n </label>\n <Input\n id=\"sched-expr\"\n value={draft.schedule}\n onChange={(e) => setDraft({ ...draft, schedule: e.target.value })}\n placeholder={draft.type === 'interval' ? '1h' : draft.type === 'cron' ? '0 9 * * *' : '2026-07-14T09:00:00Z'}\n disabled={busy}\n data-testid=\"sched-expr\"\n />\n </Stack>\n\n <Stack gap={2}>\n <label htmlFor=\"sched-tz\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Timezone</label>\n <Input\n id=\"sched-tz\"\n value={draft.timezone}\n onChange={(e) => setDraft({ ...draft, timezone: e.target.value })}\n placeholder=\"UTC\"\n disabled={busy}\n />\n </Stack>\n\n <Stack gap={2}>\n <label style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Action type</label>\n <Inline gap={2}>\n <Button\n variant={draft.actionType === 'agent' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => setDraft({ ...draft, actionType: 'agent' })}\n >\n Agent prompt\n </Button>\n <Button\n variant={draft.actionType === 'command' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => setDraft({ ...draft, actionType: 'command' })}\n >\n Shell command\n </Button>\n </Inline>\n </Stack>\n\n <Stack gap={2}>\n <label htmlFor=\"sched-prompt\" style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {draft.actionType === 'agent' ? 'Agent prompt' : 'Command'}\n </label>\n <Textarea\n id=\"sched-prompt\"\n value={draft.prompt}\n onChange={(e) => setDraft({ ...draft, prompt: e.target.value })}\n placeholder={draft.actionType === 'agent' ? 'Run the daily digest report…' : 'echo \"hello from cron\"'}\n rows={4}\n disabled={busy}\n />\n </Stack>\n\n {error !== null && (\n <div role=\"alert\" style={{ padding: 'var(--space-2)', background: 'color-mix(in oklch, var(--danger) 12%, var(--surface-0))', border: '1px solid var(--danger)', borderRadius: 'var(--radius-sm)', fontSize: 'var(--fs-12)', color: 'var(--danger)' }}>\n {error}\n </div>\n )}\n\n <Inline gap={2}>\n <Button\n variant=\"primary\"\n onClick={() => { void createSchedule(); }}\n disabled={busy || !draft.name.trim() || !draft.schedule.trim()}\n >\n {draft?.id ? 'Save' : 'Create'}\n </Button>\n <Button variant=\"ghost\" onClick={() => setDraft(null)} disabled={busy}>\n Cancel\n </Button>\n </Inline>\n </Stack>\n )}\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n"],"names":["TYPE_LABEL","TYPE_ICON","RefreshCw","Clock","Play","StatusBadge","sched","Badge","jsx","SchedulesView","res","useFetch","live","setLive","useState","draft","setDraft","busy","setBusy","error","setError","actionError","setActionError","useWsMessage","useCallback","schedules","useMemo","refresh","toggleEnabled","s","fetchJson","err","FetchError","runNow","deleteSchedule","id","createSchedule","action","jsxs","Stack","ViewHeader","Button","Plus","Skeleton","Card","CardBody","TypeIcon","Grid","Inline","Switch","Trash2","Sheet","o","SheetContent","Input","e","Textarea"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as t,j as r,P as N,b as B,i as E,u as Y,f as it,e as dt,d as Ce,n as Ie,a as Ee,m as be,h as ut,l as pt,g as ft,F as ht,D as mt,c as vt,k as gt}from"./cmdk-DVxytz9i.js";import{u as St,c as xt,a as _e}from"./index-C4Vq_2LM.js";import{c as wt,n as yt,R as Ct,p as Ne,q as It,o as Tt,C as je,g as Te,l as Pt}from"./main-
|
|
1
|
+
import{r as t,j as r,P as N,b as B,i as E,u as Y,f as it,e as dt,d as Ce,n as Ie,a as Ee,m as be,h as ut,l as pt,g as ft,F as ht,D as mt,c as vt,k as gt}from"./cmdk-DVxytz9i.js";import{u as St,c as xt,a as _e}from"./index-C4Vq_2LM.js";import{c as wt,n as yt,R as Ct,p as Ne,q as It,o as Tt,C as je,g as Te,l as Pt}from"./main-CokHAXWM.js";import{u as Rt}from"./index-CASP1n-5.js";/**
|
|
2
2
|
* @license lucide-react v0.460.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|