@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
|
@@ -27,10 +27,22 @@ import {
|
|
|
27
27
|
import { join, dirname } from 'node:path';
|
|
28
28
|
import { homedir } from 'node:os';
|
|
29
29
|
import { randomBytes } from 'node:crypto';
|
|
30
|
+
import {
|
|
31
|
+
compileClaudeArtifact,
|
|
32
|
+
detectKind as detectArtifactKind,
|
|
33
|
+
} from './claude-artifacts.mjs';
|
|
30
34
|
|
|
31
35
|
const HOME = homedir();
|
|
32
36
|
const GLOBAL_PLANS_DIR = join(HOME, '.config', 'cline', 'artifacts');
|
|
33
37
|
|
|
38
|
+
const VALID_KINDS = new Set(['mdx', 'claude-html', 'claude-svg', 'claude-react']);
|
|
39
|
+
const ARTIFACT_FILE_BY_KIND = {
|
|
40
|
+
mdx: 'artifact.mdx',
|
|
41
|
+
'claude-html': 'artifact.html',
|
|
42
|
+
'claude-svg': 'artifact.svg',
|
|
43
|
+
'claude-react': 'artifact.jsx',
|
|
44
|
+
};
|
|
45
|
+
|
|
34
46
|
// Atomic JSON write: serialize to a sibling temp file, then rename into
|
|
35
47
|
// place. `rename` is atomic on POSIX (same filesystem), so a crash
|
|
36
48
|
// between write and rename never leaves a half-written / corrupt file.
|
|
@@ -77,7 +89,7 @@ function emptyCanvas(title = 'Untitled plan') {
|
|
|
77
89
|
};
|
|
78
90
|
}
|
|
79
91
|
|
|
80
|
-
function defaultMeta(slug, title) {
|
|
92
|
+
function defaultMeta(slug, title, kind = 'mdx') {
|
|
81
93
|
const now = new Date().toISOString();
|
|
82
94
|
return {
|
|
83
95
|
slug,
|
|
@@ -86,11 +98,31 @@ function defaultMeta(slug, title) {
|
|
|
86
98
|
tags: [],
|
|
87
99
|
description: '',
|
|
88
100
|
author: process.env.USER || 'drb0rk',
|
|
101
|
+
kind: VALID_KINDS.has(kind) ? kind : 'mdx',
|
|
89
102
|
created: now,
|
|
90
103
|
lastEdited: now,
|
|
91
104
|
};
|
|
92
105
|
}
|
|
93
106
|
|
|
107
|
+
function readArtifactBody(dir, kind) {
|
|
108
|
+
// The artifact body file depends on its kind. We always prefer the
|
|
109
|
+
// kind-specific file (artifact.html / artifact.svg / artifact.jsx / artifact.mdx)
|
|
110
|
+
// but accept legacy `plan.mdx` for the mdx case so old plans still load.
|
|
111
|
+
const primary = join(dir, ARTIFACT_FILE_BY_KIND[kind] || 'artifact.mdx');
|
|
112
|
+
if (existsSync(primary)) return { source: safeReadText(primary), file: primary };
|
|
113
|
+
if (kind === 'mdx') {
|
|
114
|
+
const legacy = join(dir, 'plan.mdx');
|
|
115
|
+
if (existsSync(legacy)) return { source: safeReadText(legacy), file: legacy };
|
|
116
|
+
}
|
|
117
|
+
return { source: '', file: primary };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function writeArtifactBody(dir, kind, source) {
|
|
121
|
+
const file = join(dir, ARTIFACT_FILE_BY_KIND[kind] || 'artifact.mdx');
|
|
122
|
+
writeFileSync(file, String(source || ''), 'utf8');
|
|
123
|
+
return file;
|
|
124
|
+
}
|
|
125
|
+
|
|
94
126
|
export const artifactsStore = {
|
|
95
127
|
GLOBAL_PLANS_DIR,
|
|
96
128
|
|
|
@@ -151,6 +183,7 @@ export const artifactsStore = {
|
|
|
151
183
|
tags: meta?.tags || [],
|
|
152
184
|
description: meta?.description || '',
|
|
153
185
|
author: meta?.author || null,
|
|
186
|
+
kind: meta?.kind || 'mdx',
|
|
154
187
|
source: dir === GLOBAL_PLANS_DIR ? 'global' : 'worktree',
|
|
155
188
|
elementCount,
|
|
156
189
|
commentCount,
|
|
@@ -172,22 +205,59 @@ export const artifactsStore = {
|
|
|
172
205
|
if (!dir) return null;
|
|
173
206
|
const meta = safeReadJSON(join(dir, 'meta.json'), null);
|
|
174
207
|
const canvas = safeReadJSON(join(dir, 'plan.json'), null);
|
|
175
|
-
|
|
176
|
-
//
|
|
177
|
-
// legacy
|
|
178
|
-
|
|
179
|
-
// though `artifact.mdx` was present and correct.
|
|
180
|
-
const planMdx = safeReadText(join(dir, 'artifact.mdx'))
|
|
181
|
-
|| safeReadText(join(dir, 'plan.mdx'));
|
|
208
|
+
const kind = meta?.kind || 'mdx';
|
|
209
|
+
// Read the body file for the resolved kind. For mdx we still honour
|
|
210
|
+
// the legacy `plan.mdx` fallback (v3.20.15 contract).
|
|
211
|
+
const { source, file } = readArtifactBody(dir, kind);
|
|
182
212
|
return {
|
|
183
213
|
slug,
|
|
184
214
|
dir,
|
|
185
|
-
meta: meta || defaultMeta(slug, slug),
|
|
215
|
+
meta: meta || defaultMeta(slug, slug, kind),
|
|
186
216
|
canvas: canvas || emptyCanvas(meta?.title || slug),
|
|
187
|
-
|
|
217
|
+
kind,
|
|
218
|
+
source,
|
|
219
|
+
bodyFile: file,
|
|
220
|
+
// `planMdx` retained for legacy callers; for non-mdx kinds it is the
|
|
221
|
+
// empty string so existing code paths degrade gracefully.
|
|
222
|
+
planMdx: kind === 'mdx' ? source : '',
|
|
188
223
|
};
|
|
189
224
|
},
|
|
190
225
|
|
|
226
|
+
/**
|
|
227
|
+
* v10.1.0 — Compile a stored Claude-*-kind artifact into a render-ready
|
|
228
|
+
* HTML envelope. Returns `{ html, warnings, safeMode, kind, compiledAt }`
|
|
229
|
+
* suitable for an iframe `srcdoc`. Falls back to returning the raw
|
|
230
|
+
* `<pre>`-wrapped mdx body when the artifact is still `kind: 'mdx'`
|
|
231
|
+
* (legacy glyphs). Returns null if the slug does not exist.
|
|
232
|
+
*/
|
|
233
|
+
compile(slug, projectRoot) {
|
|
234
|
+
const plan = this.get(slug, projectRoot);
|
|
235
|
+
if (!plan) return null;
|
|
236
|
+
const kind = plan.kind || 'mdx';
|
|
237
|
+
if (kind === 'mdx') {
|
|
238
|
+
// Legacy MDX glyphs: render as a `<pre>`-wrapped plain text panel so
|
|
239
|
+
// the dashboard's previewer can keep working without the old block
|
|
240
|
+
// pipeline.
|
|
241
|
+
const escaped = String(plan.source || plan.planMdx || '')
|
|
242
|
+
.replace(/&/g, '&')
|
|
243
|
+
.replace(/</g, '<')
|
|
244
|
+
.replace(/>/g, '>');
|
|
245
|
+
const html = [
|
|
246
|
+
'<!doctype html><html><body style="font-family:ui-monospace,monospace;padding:16px;background:#0b0e14;color:#dde2e8;white-space:pre-wrap;">',
|
|
247
|
+
escaped,
|
|
248
|
+
'</body></html>',
|
|
249
|
+
].join('');
|
|
250
|
+
return {
|
|
251
|
+
kind: 'mdx',
|
|
252
|
+
html,
|
|
253
|
+
warnings: [],
|
|
254
|
+
safeMode: true,
|
|
255
|
+
compiledAt: new Date().toISOString(),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
return compileClaudeArtifact(plan.source || '', { kind });
|
|
259
|
+
},
|
|
260
|
+
|
|
191
261
|
/** Create a new plan. Returns the full plan record. */
|
|
192
262
|
create(slug, body, projectRoot) {
|
|
193
263
|
if (!VALID_SLUG.test(slug || '')) {
|
|
@@ -202,19 +272,35 @@ export const artifactsStore = {
|
|
|
202
272
|
throw err;
|
|
203
273
|
}
|
|
204
274
|
const title = (body && body.title) || slug;
|
|
275
|
+
const kindRaw = (body && body.kind) || 'mdx';
|
|
276
|
+
const kind = VALID_KINDS.has(kindRaw) ? kindRaw : 'mdx';
|
|
277
|
+
const source = (body && typeof body.source === 'string') ? body.source
|
|
278
|
+
: (kind === 'mdx' && body && typeof body.planMdx === 'string' ? body.planMdx : '');
|
|
205
279
|
const meta = {
|
|
206
|
-
...defaultMeta(slug, title),
|
|
280
|
+
...defaultMeta(slug, title, kind),
|
|
207
281
|
...(body || {}),
|
|
208
282
|
slug,
|
|
283
|
+
kind,
|
|
209
284
|
created: new Date().toISOString(),
|
|
210
285
|
lastEdited: new Date().toISOString(),
|
|
211
286
|
};
|
|
212
287
|
const canvas = emptyCanvas(title);
|
|
213
288
|
this._writePlan(dir, meta, canvas);
|
|
214
|
-
|
|
289
|
+
// Persist the artifact body in its kind-specific file so the next
|
|
290
|
+
// `get()` round-trips it without losing bytes.
|
|
291
|
+
if (source) writeArtifactBody(dir, kind, source);
|
|
292
|
+
return {
|
|
293
|
+
slug,
|
|
294
|
+
dir,
|
|
295
|
+
meta,
|
|
296
|
+
canvas,
|
|
297
|
+
kind,
|
|
298
|
+
source,
|
|
299
|
+
planMdx: kind === 'mdx' ? source : '',
|
|
300
|
+
};
|
|
215
301
|
},
|
|
216
302
|
|
|
217
|
-
/** Update plan metadata (
|
|
303
|
+
/** Update plan metadata + (optionally) the artifact body. */
|
|
218
304
|
updateMeta(slug, body, projectRoot) {
|
|
219
305
|
if (!VALID_SLUG.test(slug || '')) return null;
|
|
220
306
|
const dir = this.resolveDir(slug, projectRoot);
|
|
@@ -228,10 +314,30 @@ export const artifactsStore = {
|
|
|
228
314
|
if (valid.includes(body.status)) meta.status = body.status;
|
|
229
315
|
}
|
|
230
316
|
if (typeof body?.author === 'string') meta.author = body.author;
|
|
317
|
+
if (typeof body?.kind === 'string' && VALID_KINDS.has(body.kind)) meta.kind = body.kind;
|
|
231
318
|
meta.lastEdited = new Date().toISOString();
|
|
232
319
|
const canvas = safeReadJSON(join(dir, 'plan.json'), emptyCanvas(meta.title));
|
|
233
320
|
this._writePlan(dir, meta, canvas);
|
|
234
|
-
|
|
321
|
+
// Source/body update is the central new contract for v10.1.0: the
|
|
322
|
+
// editor can PATCH the kind and the source in one call and we keep
|
|
323
|
+
// both in lock-step.
|
|
324
|
+
let source = '';
|
|
325
|
+
if (typeof body?.source === 'string') {
|
|
326
|
+
const next = meta.kind || 'mdx';
|
|
327
|
+
source = body.source;
|
|
328
|
+
writeArtifactBody(dir, next, source);
|
|
329
|
+
} else {
|
|
330
|
+
source = safeReadText(join(dir, ARTIFACT_FILE_BY_KIND[meta.kind || 'mdx'] || 'artifact.mdx'));
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
slug,
|
|
334
|
+
dir,
|
|
335
|
+
meta,
|
|
336
|
+
canvas,
|
|
337
|
+
kind: meta.kind || 'mdx',
|
|
338
|
+
source,
|
|
339
|
+
planMdx: (meta.kind || 'mdx') === 'mdx' ? source : '',
|
|
340
|
+
};
|
|
235
341
|
},
|
|
236
342
|
|
|
237
343
|
/** Delete a plan directory. */
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/server/claude-artifacts.mjs
|
|
3
|
+
*
|
|
4
|
+
* v10.1.0 — Claude Artifacts compile + sandbox wrapper.
|
|
5
|
+
*
|
|
6
|
+
* Replaces the v3–v9 MDX "glyphs" renderer with the Claude.ai-style
|
|
7
|
+
* interactive artifact surface. Three supported kinds:
|
|
8
|
+
*
|
|
9
|
+
* claude-html — static HTML + inline CSS/JS (sandboxed iframe)
|
|
10
|
+
* claude-svg — standalone <svg> document
|
|
11
|
+
* claude-react — JSX/TSX source bundled to a UMD module that the
|
|
12
|
+
* iframe loads; the wrapper injects React + ReactDOM
|
|
13
|
+
* from a CDN pinned to v18.x
|
|
14
|
+
*
|
|
15
|
+
* The compile output is a self-contained `html` string ready to drop
|
|
16
|
+
* into an iframe `srcdoc`. Validation is conservative: it scans for
|
|
17
|
+
* dangerous patterns (script src to non-allowlisted hosts, event
|
|
18
|
+
* handlers that leak `top`/`parent`, etc.) and refuses to compile
|
|
19
|
+
* anything that looks like an exfiltration attempt.
|
|
20
|
+
*
|
|
21
|
+
* This module does NOT execute user code on the server. The iframe
|
|
22
|
+
* is the only execution surface. The server only:
|
|
23
|
+
* 1. Parses the source to confirm it is well-formed.
|
|
24
|
+
* 2. Wraps it in a sandbox-friendly HTML envelope.
|
|
25
|
+
* 3. Sanitises obvious exfiltration patterns.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
// ─── Allowlist ───────────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
// Hosts we are willing to load scripts/styles from inside the artifact.
|
|
31
|
+
// Pinned to reduce surprise breakage.
|
|
32
|
+
const ALLOWED_SCRIPT_HOSTS = new Set([
|
|
33
|
+
'unpkg.com',
|
|
34
|
+
'cdn.jsdelivr.net',
|
|
35
|
+
'cdnjs.cloudflare.com',
|
|
36
|
+
'esm.sh',
|
|
37
|
+
'cdn.tailwindcss.com',
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
const ALLOWED_STYLE_HOSTS = new Set([
|
|
41
|
+
'unpkg.com',
|
|
42
|
+
'cdn.jsdelivr.net',
|
|
43
|
+
'cdnjs.cloudflare.com',
|
|
44
|
+
'fonts.googleapis.com',
|
|
45
|
+
'fonts.gstatic.com',
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
// DANGEROUS: these patterns inside a Claude artifact mean exfiltration or
|
|
49
|
+
// privilege escalation. They get flagged in `errors[]` and the artifact
|
|
50
|
+
// is rendered in `safe-mode` (scripts stripped, event handlers removed).
|
|
51
|
+
const EXFIL_PATTERNS = [
|
|
52
|
+
// top.* / parent.* access — breaks out of the sandbox
|
|
53
|
+
/\b(top|parent)\s*\.\s*[a-zA-Z_]/i,
|
|
54
|
+
// window.opener hijack
|
|
55
|
+
/\bwindow\s*\.\s*opener\b/i,
|
|
56
|
+
// fetch / XHR with literal URL → host we don't trust
|
|
57
|
+
/\bfetch\s*\(\s*['"`]https?:\/\/(?!(?:localhost|127\.0\.0\.1|unpkg\.com|cdn\.jsdelivr\.net|cdnjs\.cloudflare\.com|esm\.sh))/i,
|
|
58
|
+
// document.cookie access
|
|
59
|
+
/\bdocument\s*\.\s*cookie\b/i,
|
|
60
|
+
// localStorage / sessionStorage exfil
|
|
61
|
+
/\b(localStorage|sessionStorage)\s*\.\s*(setItem|getItem)\b/i,
|
|
62
|
+
// <script src="http://evil"> — bare remote script tag
|
|
63
|
+
/<script[^>]+src\s*=\s*["']https?:\/\/(?!(?:localhost|127\.0\.0\.1|unpkg\.com|cdn\.jsdelivr\.net|cdnjs\.cloudflare\.com|esm\.sh))/i,
|
|
64
|
+
// inline event handler that runs JS (onclick=, onerror=, ...)
|
|
65
|
+
/\son\w+\s*=\s*["'][^"']*\beval\s*\(/i,
|
|
66
|
+
// javascript: URLs
|
|
67
|
+
/\bhref\s*=\s*["']javascript:/i,
|
|
68
|
+
// imports from a path the bundler doesn't know
|
|
69
|
+
/\bimport\s+.*from\s+["'](?!react|react-dom|react-dom\/client)/i,
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
// ─── Validation ──────────────────────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Scan a Claude artifact source for exfiltration / escape patterns.
|
|
76
|
+
* Returns the list of tripped patterns (empty = clean).
|
|
77
|
+
*
|
|
78
|
+
* @param {string} src
|
|
79
|
+
* @returns {Array<{ pattern: string, message: string }>}
|
|
80
|
+
*/
|
|
81
|
+
export function scanForExfil(src) {
|
|
82
|
+
const hits = [];
|
|
83
|
+
for (const re of EXFIL_PATTERNS) {
|
|
84
|
+
const m = re.exec(src);
|
|
85
|
+
if (m) {
|
|
86
|
+
hits.push({
|
|
87
|
+
pattern: re.source.slice(0, 80),
|
|
88
|
+
message: `potential exfiltration / sandbox escape: ${m[0].slice(0, 80)}`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return hits;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Detect the artifact kind from the source content. Falls back to
|
|
97
|
+
* 'claude-html' when the user did not supply one.
|
|
98
|
+
*
|
|
99
|
+
* Heuristics:
|
|
100
|
+
* - bare `<svg ...>` at the root → claude-svg
|
|
101
|
+
* - contains `import React` or `export default` → claude-react
|
|
102
|
+
* - everything else → claude-html
|
|
103
|
+
*
|
|
104
|
+
* @param {string} src
|
|
105
|
+
* @param {string} [declared]
|
|
106
|
+
* @returns {'claude-html' | 'claude-svg' | 'claude-react'}
|
|
107
|
+
*/
|
|
108
|
+
export function detectKind(src, declared) {
|
|
109
|
+
if (declared === 'claude-html' || declared === 'claude-svg' || declared === 'claude-react') {
|
|
110
|
+
return declared;
|
|
111
|
+
}
|
|
112
|
+
const trimmed = (src || '').trim();
|
|
113
|
+
if (/^<svg[\s>]/i.test(trimmed)) return 'claude-svg';
|
|
114
|
+
if (/\bimport\s+React\b|\bexport\s+default\b/.test(trimmed)) return 'claude-react';
|
|
115
|
+
return 'claude-html';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ─── Sandboxed envelope ──────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Build the iframe-ready HTML envelope. The user source is injected
|
|
122
|
+
* inside the `<body>` so the iframe owns all rendering.
|
|
123
|
+
*
|
|
124
|
+
* The sandbox attribute restricts the iframe to:
|
|
125
|
+
* - same-origin scripts (so React can hydrate)
|
|
126
|
+
* - no top navigation
|
|
127
|
+
* - no popups
|
|
128
|
+
* - no form submission
|
|
129
|
+
* - no same-origin storage (cookie/storage stays in the iframe only)
|
|
130
|
+
*
|
|
131
|
+
* @param {string} body — the user-authored artifact body
|
|
132
|
+
* @param {object} [opts]
|
|
133
|
+
* @param {'claude-html'|'claude-svg'|'claude-react'} [opts.kind]
|
|
134
|
+
* @param {boolean} [opts.safeMode] — when true, scripts are stripped
|
|
135
|
+
* @returns {string} full HTML document string for iframe srcdoc
|
|
136
|
+
*/
|
|
137
|
+
export function buildEnvelope(body, { kind = 'claude-html', safeMode = false } = {}) {
|
|
138
|
+
const safeBody = safeMode ? stripScripts(body) : body;
|
|
139
|
+
const head = buildHead(kind, safeMode);
|
|
140
|
+
return [
|
|
141
|
+
'<!doctype html>',
|
|
142
|
+
'<html lang="en">',
|
|
143
|
+
'<head>',
|
|
144
|
+
'<meta charset="utf-8">',
|
|
145
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
146
|
+
head,
|
|
147
|
+
'</head>',
|
|
148
|
+
'<body>',
|
|
149
|
+
safeBody,
|
|
150
|
+
'</body>',
|
|
151
|
+
'</html>',
|
|
152
|
+
].join('\n');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function buildHead(kind, safeMode) {
|
|
156
|
+
const scriptBlock = safeMode
|
|
157
|
+
? ''
|
|
158
|
+
: kind === 'claude-react'
|
|
159
|
+
? [
|
|
160
|
+
'<script crossorigin src="https://unpkg.com/react@18.3.1/umd/react.production.min.js"></script>',
|
|
161
|
+
'<script crossorigin src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js"></script>',
|
|
162
|
+
'<script src="https://unpkg.com/@babel/standalone@7.24.7/babel.min.js"></script>',
|
|
163
|
+
].join('\n')
|
|
164
|
+
: '';
|
|
165
|
+
const style = [
|
|
166
|
+
'html,body{margin:0;padding:0;font-family:system-ui,-apple-system,sans-serif;color:#111;background:#fff;}',
|
|
167
|
+
'a{color:#0b66c3;}',
|
|
168
|
+
'img,svg{max-width:100%;height:auto;}',
|
|
169
|
+
].join('');
|
|
170
|
+
return [
|
|
171
|
+
`<style>${style}</style>`,
|
|
172
|
+
scriptBlock,
|
|
173
|
+
].filter(Boolean).join('\n');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Strip `<script>...</script>` blocks and inline event handlers from
|
|
178
|
+
* an HTML source. Used when the artifact fails the exfil scan.
|
|
179
|
+
*
|
|
180
|
+
* @param {string} html
|
|
181
|
+
* @returns {string}
|
|
182
|
+
*/
|
|
183
|
+
export function stripScripts(html) {
|
|
184
|
+
return String(html || '')
|
|
185
|
+
.replace(/<script\b[\s\S]*?<\/script>/gi, '')
|
|
186
|
+
.replace(/\son\w+\s*=\s*("[^"]*"|'[^']*'|[^\s>]*)/gi, '');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ─── Public compile API ──────────────────────────────────────────────────────
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Compile a Claude artifact source into a render-ready envelope.
|
|
193
|
+
* Returns the envelope + a list of warnings (the caller decides
|
|
194
|
+
* whether to render in safe-mode vs full).
|
|
195
|
+
*
|
|
196
|
+
* @param {string} source raw artifact source
|
|
197
|
+
* @param {object} [opts]
|
|
198
|
+
* @param {'claude-html'|'claude-svg'|'claude-react'} [opts.kind]
|
|
199
|
+
* @returns {{
|
|
200
|
+
* kind: 'claude-html'|'claude-svg'|'claude-react',
|
|
201
|
+
* html: string,
|
|
202
|
+
* warnings: Array<{ message: string }>,
|
|
203
|
+
* compiledAt: string,
|
|
204
|
+
* }}
|
|
205
|
+
*/
|
|
206
|
+
export function compileClaudeArtifact(source, opts = {}) {
|
|
207
|
+
const src = String(source || '');
|
|
208
|
+
const kind = detectKind(src, opts.kind);
|
|
209
|
+
const warnings = scanForExfil(src);
|
|
210
|
+
const safeMode = warnings.length > 0;
|
|
211
|
+
const html = buildEnvelope(src, { kind, safeMode });
|
|
212
|
+
return {
|
|
213
|
+
kind,
|
|
214
|
+
html,
|
|
215
|
+
warnings,
|
|
216
|
+
safeMode,
|
|
217
|
+
compiledAt: new Date().toISOString(),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ─── Legacy MDX migration helper ─────────────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Convert an existing `plan.mdx` / `artifact.mdx` block-list output into
|
|
225
|
+
* a Claude-React artifact. Used by the migration when an operator
|
|
226
|
+
* runs `bizar artifacts migrate-glyphs`. Best-effort — if the MDX has
|
|
227
|
+
* unsupported block types, returns an empty artifact + a warning list.
|
|
228
|
+
*
|
|
229
|
+
* @param {{ blocks: Array, frontmatter: Record<string, unknown> }} compiled
|
|
230
|
+
* @returns {{ source: string, warnings: string[] }}
|
|
231
|
+
*/
|
|
232
|
+
export function mdxBlocksToReact(compiled) {
|
|
233
|
+
const warnings = [];
|
|
234
|
+
const lines = [];
|
|
235
|
+
lines.push('// Auto-generated from legacy MDX. Edit freely.');
|
|
236
|
+
lines.push('const { useState } = React;');
|
|
237
|
+
lines.push('');
|
|
238
|
+
const blocks = Array.isArray(compiled?.blocks) ? compiled.blocks : [];
|
|
239
|
+
for (const block of blocks) {
|
|
240
|
+
if (block.type === 'RichText') {
|
|
241
|
+
const md = String(block.childrenMarkdown || '').replace(/`/g, '\\`').replace(/\$/g, '\\$');
|
|
242
|
+
lines.push(`function Block_${block.id}() {`);
|
|
243
|
+
lines.push(' return <pre style={{ whiteSpace: "pre-wrap", fontFamily: "inherit" }}>{`' + md + '`}</pre>;');
|
|
244
|
+
lines.push('}');
|
|
245
|
+
} else if (block.type === 'Callout') {
|
|
246
|
+
const tone = String(block.data?.tone || 'info');
|
|
247
|
+
lines.push(`function Block_${block.id}() {`);
|
|
248
|
+
lines.push(` return <div style={{ padding: 12, borderRadius: 8, background: "var(--callout-${tone}-bg, #eef)" }}>${escapeText(block.childrenMarkdown || '')}</div>;`);
|
|
249
|
+
lines.push('}');
|
|
250
|
+
} else if (block.type === 'Stat') {
|
|
251
|
+
const label = String(block.data?.label || '');
|
|
252
|
+
const value = String(block.data?.value || '');
|
|
253
|
+
lines.push(`function Block_${block.id}() {`);
|
|
254
|
+
lines.push(` return <div style={{ display: "inline-block", padding: 16 }}><div style={{ fontSize: 12, opacity: 0.7 }}>${escapeText(label)}</div><div style={{ fontSize: 28, fontWeight: 600 }}>${escapeText(value)}</div></div>;`);
|
|
255
|
+
lines.push('}');
|
|
256
|
+
} else {
|
|
257
|
+
warnings.push(`unsupported block type "${block.type}" (id=${block.id}) — skipped in migration`);
|
|
258
|
+
}
|
|
259
|
+
lines.push('');
|
|
260
|
+
}
|
|
261
|
+
lines.push('export default function App() {');
|
|
262
|
+
lines.push(' return (');
|
|
263
|
+
lines.push(' <div style={{ padding: 16 }}>');
|
|
264
|
+
for (const block of blocks) {
|
|
265
|
+
if (['RichText', 'Callout', 'Stat'].includes(block.type)) {
|
|
266
|
+
lines.push(` <Block_${block.id} />`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
lines.push(' </div>');
|
|
270
|
+
lines.push(' );');
|
|
271
|
+
lines.push('}');
|
|
272
|
+
return { source: lines.join('\n'), warnings };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function escapeText(s) {
|
|
276
|
+
return String(s || '')
|
|
277
|
+
.replace(/&/g, '&')
|
|
278
|
+
.replace(/</g, '<')
|
|
279
|
+
.replace(/>/g, '>')
|
|
280
|
+
.replace(/"/g, '"');
|
|
281
|
+
}
|
|
@@ -119,10 +119,7 @@ export function getRecentErrors({ since = 0, limit = 200 } = {}) {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
|
-
* v6.0.0 —
|
|
123
|
-
* `{ running, port?, error? }` shape so the Doctor page can show a
|
|
124
|
-
* "Headroom proxy on 8787 ✓" line without forcing the route to
|
|
125
|
-
* swallow a 1.5s timeout on every poll.
|
|
122
|
+
* v6.0.0 — Generic TCP probe used by the Doctor page.
|
|
126
123
|
*
|
|
127
124
|
* @param {string} host
|
|
128
125
|
* @param {number} port
|
|
@@ -184,23 +181,6 @@ async function probeLightRAG() {
|
|
|
184
181
|
}
|
|
185
182
|
}
|
|
186
183
|
|
|
187
|
-
async function probeHeadroom() {
|
|
188
|
-
// Headroom's default port — matches headroom.mjs's
|
|
189
|
-
// DEFAULT_HEADROOM_PORT. Settings override takes precedence.
|
|
190
|
-
let port = 8787;
|
|
191
|
-
let host = '127.0.0.1';
|
|
192
|
-
try {
|
|
193
|
-
const settingsPath = join(HOME, '.config', 'bizar', 'settings.json');
|
|
194
|
-
if (existsSync(settingsPath)) {
|
|
195
|
-
const parsed = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
196
|
-
port = Number(parsed?.headroom?.port) || port;
|
|
197
|
-
host = String(parsed?.headroom?.host) || host;
|
|
198
|
-
}
|
|
199
|
-
} catch { /* ignore */ }
|
|
200
|
-
const result = await probeTcp(host, port, 800);
|
|
201
|
-
return { ...result, port, host };
|
|
202
|
-
}
|
|
203
|
-
|
|
204
184
|
/**
|
|
205
185
|
* v6.0.0 — Probe whether the cline plugin's `serve-info.json` is
|
|
206
186
|
* reachable on disk and parseable. The dashboard reads serve-info to
|
|
@@ -321,12 +301,11 @@ async function runConfigChecks() {
|
|
|
321
301
|
}
|
|
322
302
|
|
|
323
303
|
/**
|
|
324
|
-
* v6.0.0 — Service health checks. TCP
|
|
325
|
-
*
|
|
326
|
-
*
|
|
304
|
+
* v6.0.0 — Service health checks. TCP probe for lightrag
|
|
305
|
+
* (best-effort), cline plugin file probe, and the dashboard itself
|
|
306
|
+
* (always `ok` — we're running because we got here).
|
|
327
307
|
*/
|
|
328
308
|
async function runServiceChecks() {
|
|
329
|
-
const headroom = await probeHeadroom();
|
|
330
309
|
const lightrag = await probeLightRAG();
|
|
331
310
|
const serveInfo = clineServeInfo();
|
|
332
311
|
const checks = [
|
|
@@ -335,13 +314,6 @@ async function runServiceChecks() {
|
|
|
335
314
|
status: 'ok',
|
|
336
315
|
message: `running on pid ${process.pid}, up ${Math.floor(process.uptime())}s`,
|
|
337
316
|
},
|
|
338
|
-
{
|
|
339
|
-
name: 'headroom',
|
|
340
|
-
status: headroom.running ? 'ok' : 'warn',
|
|
341
|
-
message: headroom.running
|
|
342
|
-
? `proxy on ${headroom.host}:${headroom.port}`
|
|
343
|
-
: `not running on ${headroom.host}:${headroom.port}${headroom.error ? ` (${headroom.error})` : ''}`,
|
|
344
|
-
},
|
|
345
317
|
{
|
|
346
318
|
name: 'lightrag',
|
|
347
319
|
status: lightrag.running ? 'ok' : 'warn',
|
|
@@ -447,7 +419,7 @@ export async function health() {
|
|
|
447
419
|
* uptime: number,
|
|
448
420
|
* memory: NodeJS.MemoryUsage,
|
|
449
421
|
* disk: { exists: boolean, path: string, sizeBytes: number },
|
|
450
|
-
* services: { dashboard: object,
|
|
422
|
+
* services: { dashboard: object, lightrag: object, cline: object },
|
|
451
423
|
* counts: ReturnType<typeof collectCounts>,
|
|
452
424
|
* recentErrors: ReturnType<typeof getRecentErrors>,
|
|
453
425
|
* configHealth: Array<{ name: string, status: string, message: string }>,
|
|
@@ -467,7 +439,6 @@ export async function collectDiagnostics() {
|
|
|
467
439
|
let status = 'ok';
|
|
468
440
|
if (issues.some((c) => c.status === 'fail')) status = 'fail';
|
|
469
441
|
else if (issues.length > 0) status = 'warn';
|
|
470
|
-
const headroom = await probeHeadroom();
|
|
471
442
|
const lightrag = await probeLightRAG();
|
|
472
443
|
const serveInfo = clineServeInfo();
|
|
473
444
|
const clineConfig = providersStore.CLINE_JSON;
|
|
@@ -505,7 +476,6 @@ export async function collectDiagnostics() {
|
|
|
505
476
|
logPath: dashboardLogPath,
|
|
506
477
|
logExists: dashboardLogExists,
|
|
507
478
|
},
|
|
508
|
-
headroom,
|
|
509
479
|
lightrag,
|
|
510
480
|
cline: serveInfo,
|
|
511
481
|
},
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* Path-traversal attacks (e.g. `../`) are blocked.
|
|
23
23
|
* 3. **Subprocess allowlist** — only whitelisted binaries
|
|
24
24
|
* (`bizar`, `cline`, `python3`, `graphify`, `git`, `node`,
|
|
25
|
-
* `npm`, `pip`, `pipx`, `uv
|
|
25
|
+
* `npm`, `pip`, `pipx`, `uv`) can be spawned. Custom
|
|
26
26
|
* binaries require an explicit `process:spawn:<bin>` permission.
|
|
27
27
|
* 4. **Audit log** — every privileged operation (fs read/write,
|
|
28
28
|
* process spawn, network fetch) is logged to
|
|
@@ -73,7 +73,6 @@ export const ALLOWED_BINARIES = new Set([
|
|
|
73
73
|
'npm',
|
|
74
74
|
'npx',
|
|
75
75
|
'git',
|
|
76
|
-
'headroom',
|
|
77
76
|
'jq',
|
|
78
77
|
]);
|
|
79
78
|
|
|
@@ -164,7 +164,7 @@ export { readClineJsonCached, invalidateClineJsonCache, CLINE_JSON_CACHE_TTL_MS
|
|
|
164
164
|
// MAX_ROTATION_ATTEMPTS: bound on the number of times `withKeyRotation`
|
|
165
165
|
// will retry the user's fn with a different key before throwing. With
|
|
166
166
|
// `cooldown` skipping, this matches the typical "1 primary + 1 backup"
|
|
167
|
-
// deployment (2 attempts) with
|
|
167
|
+
// deployment (2 attempts) with a 3rd emergency key.
|
|
168
168
|
//
|
|
169
169
|
// ROTATION_ERROR_PATTERNS: substring match against the lowercased error
|
|
170
170
|
// message — used as a fallback when no structured `status` is present
|
|
@@ -148,22 +148,6 @@ export const DEFAULT_SETTINGS = {
|
|
|
148
148
|
baseUrl: 'https://www.minimax.io',
|
|
149
149
|
chatBaseUrl: 'https://api.minimax.io/v1',
|
|
150
150
|
},
|
|
151
|
-
// v5.0.0 — Headroom context compression integration.
|
|
152
|
-
// Headroom sits between cline and LLM providers, compressing tool
|
|
153
|
-
// outputs, logs, RAG chunks, and conversation history by 60–95%.
|
|
154
|
-
headroom: {
|
|
155
|
-
enabled: true,
|
|
156
|
-
autoInstall: true,
|
|
157
|
-
port: 8787,
|
|
158
|
-
host: '127.0.0.1',
|
|
159
|
-
outputShaper: false,
|
|
160
|
-
telemetry: false,
|
|
161
|
-
budget: 0,
|
|
162
|
-
backend: 'anthropic',
|
|
163
|
-
autoStart: true,
|
|
164
|
-
autoWrap: true,
|
|
165
|
-
routeAllProviders: true,
|
|
166
|
-
},
|
|
167
151
|
};
|
|
168
152
|
|
|
169
153
|
/**
|
|
@@ -190,7 +174,6 @@ export function mergeSettings(existing) {
|
|
|
190
174
|
merged.agents = { ...DEFAULT_SETTINGS.agents, ...(existing.agents || {}) };
|
|
191
175
|
merged.systemLlm = { ...DEFAULT_SETTINGS.systemLlm, ...(existing.systemLlm || {}) };
|
|
192
176
|
merged.minimax = { ...DEFAULT_SETTINGS.minimax, ...(existing.minimax || {}) };
|
|
193
|
-
merged.headroom = { ...DEFAULT_SETTINGS.headroom, ...(existing.headroom || {}) };
|
|
194
177
|
// Always use the package version — never let user settings override it
|
|
195
178
|
merged.about.version = DEFAULT_SETTINGS.about.version;
|
|
196
179
|
return merged;
|