@polderlabs/bizar 10.1.0 → 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/skills/headroom/SKILL.md +94 -0
- package/bizar-dash/src/server/api.mjs +11 -0
- 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/headroom.mjs +649 -0
- 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/headroom.mjs +126 -0
- package/bizar-dash/src/server/routes/model-router.mjs +55 -0
- package/bizar-dash/src/server/routes/model-router.test.mjs +28 -0
- package/bizar-dash/src/server/routes/sessions.mjs +80 -0
- 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/headroom-install.test.mjs +173 -0
- package/bizar-dash/tests/headroom-settings.test.mjs +126 -0
- package/bizar-dash/tests/headroom-status.test.mjs +117 -0
- package/cli/commands/headroom.mjs +204 -0
- 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/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
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cli/commands/headroom.mjs
|
|
3
|
+
*
|
|
4
|
+
* Headroom context compression CLI.
|
|
5
|
+
* v3.17.0+ — status, stats, install, wrap, unwrap, start, stop, doctor.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { homedir } from 'node:os';
|
|
11
|
+
import { spawn } from 'node:child_process';
|
|
12
|
+
|
|
13
|
+
const HOME = homedir();
|
|
14
|
+
const BIZAR_HOME = join(HOME, '.config', 'bizar');
|
|
15
|
+
|
|
16
|
+
// ── Dashboard connection ────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
function readDashboardConn() {
|
|
19
|
+
const portFile = join(BIZAR_HOME, 'dashboard.port');
|
|
20
|
+
const authFile = join(BIZAR_HOME, 'dashboard-secret');
|
|
21
|
+
let port = 4321;
|
|
22
|
+
let secret = '';
|
|
23
|
+
try {
|
|
24
|
+
if (existsSync(portFile)) {
|
|
25
|
+
const parsed = parseInt(readFileSync(portFile, 'utf8').trim(), 10);
|
|
26
|
+
if (Number.isFinite(parsed) && parsed > 0) port = parsed;
|
|
27
|
+
}
|
|
28
|
+
} catch { /* ignore */ }
|
|
29
|
+
try {
|
|
30
|
+
if (existsSync(authFile)) secret = readFileSync(authFile, 'utf8').trim();
|
|
31
|
+
} catch { /* ignore */ }
|
|
32
|
+
return { port, secret };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ── Help ───────────────────────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
export function showHeadroomHelp() {
|
|
38
|
+
console.log(`
|
|
39
|
+
bizar headroom — Manage Headroom context compression
|
|
40
|
+
|
|
41
|
+
Usage:
|
|
42
|
+
bizar headroom status Show live status (installed, proxy, wrapped)
|
|
43
|
+
bizar headroom stats Show compression stats for the last 24h
|
|
44
|
+
bizar headroom install Install headroom via pip or npm
|
|
45
|
+
bizar headroom wrap Wrap cline to route through the proxy
|
|
46
|
+
bizar headroom unwrap Unwrap cline
|
|
47
|
+
bizar headroom start Start the proxy server
|
|
48
|
+
bizar headroom stop Stop the proxy server
|
|
49
|
+
bizar headroom doctor Run headroom doctor health check
|
|
50
|
+
|
|
51
|
+
Examples:
|
|
52
|
+
bizar headroom status
|
|
53
|
+
bizar headroom stats
|
|
54
|
+
bizar headroom install
|
|
55
|
+
bizar headroom wrap
|
|
56
|
+
`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ── API helpers ────────────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
async function apiGet(path) {
|
|
62
|
+
const { port, secret } = readDashboardConn();
|
|
63
|
+
const baseUrl = `http://127.0.0.1:${port}`;
|
|
64
|
+
const url = `${baseUrl}${path}`;
|
|
65
|
+
const headers = { accept: 'application/json' };
|
|
66
|
+
if (secret) headers.authorization = `Basic ${Buffer.from(`cline:${secret}`).toString('base64')}`;
|
|
67
|
+
const res = await fetch(url, { method: 'GET', headers });
|
|
68
|
+
const text = await res.text();
|
|
69
|
+
let data = null;
|
|
70
|
+
try { data = text ? JSON.parse(text) : null; } catch { /* ignore */ }
|
|
71
|
+
if (!res.ok) throw new Error(`${path}: ${data?.message || data?.error || res.statusText}`);
|
|
72
|
+
return data;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function apiPost(path, body = {}) {
|
|
76
|
+
const { port, secret } = readDashboardConn();
|
|
77
|
+
const baseUrl = `http://127.0.0.1:${port}`;
|
|
78
|
+
const url = `${baseUrl}${path}`;
|
|
79
|
+
const headers = { 'content-type': 'application/json', accept: 'application/json' };
|
|
80
|
+
if (secret) headers.authorization = `Basic ${Buffer.from(`cline:${secret}`).toString('base64')}`;
|
|
81
|
+
const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) });
|
|
82
|
+
const text = await res.text();
|
|
83
|
+
let data = null;
|
|
84
|
+
try { data = text ? JSON.parse(text) : null; } catch { /* ignore */ }
|
|
85
|
+
if (!res.ok) throw new Error(`${path}: ${data?.message || data?.error || res.statusText}`);
|
|
86
|
+
return data;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ── Command runner ────────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
async function runHeadroomCommand(headroomArgs) {
|
|
92
|
+
const sub = headroomArgs[0];
|
|
93
|
+
const flags = headroomArgs.slice(1).filter((a) => a.startsWith('-'));
|
|
94
|
+
const positional = headroomArgs.slice(1).filter((a) => !a.startsWith('-'));
|
|
95
|
+
|
|
96
|
+
if (!sub || sub === '--help' || sub === '-h' || flags.includes('--help') || flags.includes('-h')) {
|
|
97
|
+
showHeadroomHelp();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (sub === 'status') {
|
|
102
|
+
const s = await apiGet('/api/headroom/status');
|
|
103
|
+
console.log('');
|
|
104
|
+
console.log(chalk.bold(' Headroom status'));
|
|
105
|
+
console.log('');
|
|
106
|
+
console.log(` ${chalk.dim('installed:')} ${s.installed ? chalk.green('yes') : chalk.red('no')} ${s.version || ''}`);
|
|
107
|
+
console.log(` ${chalk.dim('proxy:')} ${s.proxyRunning ? chalk.green('running') : chalk.yellow('stopped')} ${s.proxyPort ? `@ ${s.proxyPort}` : ''} ${s.proxyPid ? `(PID ${s.proxyPid})` : ''}`);
|
|
108
|
+
console.log(` ${chalk.dim('wrapped:')} ${s.wrapped ? chalk.green('yes') : chalk.yellow('no')}`);
|
|
109
|
+
console.log(` ${chalk.dim('healthy:')} ${s.healthy === 'ok' ? chalk.green('ok') : s.healthy === 'warn' ? chalk.yellow('warn') : chalk.red('fail')}`);
|
|
110
|
+
if (s.messages && s.messages.length > 0) {
|
|
111
|
+
console.log('');
|
|
112
|
+
for (const m of s.messages) {
|
|
113
|
+
console.log(` ${m}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
console.log('');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (sub === 'stats') {
|
|
121
|
+
const hours = parseInt(positional[0], 10) || 24;
|
|
122
|
+
const st = await apiGet(`/api/headroom/stats?hours=${hours}`);
|
|
123
|
+
console.log('');
|
|
124
|
+
console.log(chalk.bold(` Headroom stats (${hours}h)`));
|
|
125
|
+
console.log('');
|
|
126
|
+
if (st.error) {
|
|
127
|
+
console.log(chalk.yellow(` ${st.error}`));
|
|
128
|
+
} else {
|
|
129
|
+
console.log(` ${chalk.dim('tokens saved:')} ${(st.tokensSaved || 0).toLocaleString()}`);
|
|
130
|
+
console.log(` ${chalk.dim('compression:')} ${st.compressionRatio ? `${Math.round(st.compressionRatio * 100)}%` : '—'}`);
|
|
131
|
+
console.log(` ${chalk.dim('cache hits:')} ${st.cacheHits ?? '—'}`);
|
|
132
|
+
console.log(` ${chalk.dim('transforms:')} ${st.transforms ?? '—'}`);
|
|
133
|
+
}
|
|
134
|
+
console.log('');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (sub === 'install') {
|
|
139
|
+
const r = await apiPost('/api/headroom/install', { force: true });
|
|
140
|
+
if (r.installed) {
|
|
141
|
+
console.log(chalk.green(` ✓ Headroom installed via ${r.method}${r.version ? ` (${r.version})` : ''}`));
|
|
142
|
+
} else {
|
|
143
|
+
console.log(chalk.red(' ✗ Install failed. Try: pip install "headroom-ai[all]"'));
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (sub === 'wrap') {
|
|
149
|
+
const port = parseInt(positional[0], 10) || 8787;
|
|
150
|
+
const r = await apiPost('/api/headroom/wrap', { port });
|
|
151
|
+
if (r.ok) {
|
|
152
|
+
console.log(chalk.green(` ✓ cline wrapped with Headroom on port ${port}`));
|
|
153
|
+
} else {
|
|
154
|
+
console.log(chalk.red(` ✗ Wrap failed: ${r.log || 'unknown error'}`));
|
|
155
|
+
}
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (sub === 'unwrap') {
|
|
160
|
+
const r = await apiPost('/api/headroom/unwrap');
|
|
161
|
+
if (r.ok) {
|
|
162
|
+
console.log(chalk.green(' ✓ cline unwrapped from Headroom'));
|
|
163
|
+
} else {
|
|
164
|
+
console.log(chalk.red(' ✗ Unwrap failed'));
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (sub === 'start') {
|
|
170
|
+
const port = parseInt(positional[0], 10) || 8787;
|
|
171
|
+
const r = await apiPost('/api/headroom/proxy/start', { port, host: '127.0.0.1' });
|
|
172
|
+
if (r.ok) {
|
|
173
|
+
console.log(chalk.green(` ✓ Proxy started on 127.0.0.1:${port} (PID ${r.pid})`));
|
|
174
|
+
} else {
|
|
175
|
+
console.log(chalk.red(' ✗ Proxy start failed'));
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (sub === 'stop') {
|
|
181
|
+
const r = await apiPost('/api/headroom/proxy/stop');
|
|
182
|
+
if (r.ok) {
|
|
183
|
+
console.log(chalk.green(' ✓ Proxy stopped'));
|
|
184
|
+
} else {
|
|
185
|
+
console.log(chalk.red(' ✗ Proxy stop failed'));
|
|
186
|
+
}
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (sub === 'doctor') {
|
|
191
|
+
// Run `headroom doctor` locally
|
|
192
|
+
const child = spawn('headroom', ['doctor'], { stdio: 'inherit' });
|
|
193
|
+
await new Promise((resolve) => child.on('close', resolve));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
console.error(chalk.red(` ✗ Unknown headroom subcommand: ${sub}`));
|
|
198
|
+
showHeadroomHelp();
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export async function run(name, args, isHelpRequest) {
|
|
203
|
+
await runHeadroomCommand(args);
|
|
204
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polderlabs/bizar",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.2.0",
|
|
4
4
|
"description": "Norse-pantheon multi-agent system for Claude Code — 14 agents across 4 cost tiers with cost-aware routing, plans, and a configurable agent harness. Ships as a single npm package with the dashboard server, Claude Code MCP server, and typed SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/agent/cron.ts
|
|
3
|
+
*
|
|
4
|
+
* Pillar A — Cron scheduled tasks.
|
|
5
|
+
*
|
|
6
|
+
* Exports:
|
|
7
|
+
* addCronTask({ cron, prompt, recurring })
|
|
8
|
+
* listCronTasks()
|
|
9
|
+
* removeCronTask(id)
|
|
10
|
+
*
|
|
11
|
+
* Persists to `.bizar/cron.json`.
|
|
12
|
+
*/
|
|
13
|
+
export interface CronTask {
|
|
14
|
+
id: string;
|
|
15
|
+
cron: string;
|
|
16
|
+
prompt: string;
|
|
17
|
+
recurring: boolean;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Add a cron task.
|
|
22
|
+
*
|
|
23
|
+
* @param opts.cron — cron expression (e.g. "0 * * * *")
|
|
24
|
+
* @param opts.prompt — prompt to execute on trigger
|
|
25
|
+
* @param opts.recurring — if false, task is removed after first run
|
|
26
|
+
* @param opts.repoRoot — optional repo root override
|
|
27
|
+
* @returns the created CronTask
|
|
28
|
+
*/
|
|
29
|
+
export declare function addCronTask(opts: {
|
|
30
|
+
cron: string;
|
|
31
|
+
prompt: string;
|
|
32
|
+
recurring?: boolean;
|
|
33
|
+
repoRoot?: string;
|
|
34
|
+
}): CronTask;
|
|
35
|
+
/**
|
|
36
|
+
* List all cron tasks.
|
|
37
|
+
*/
|
|
38
|
+
export declare function listCronTasks(repoRoot?: string): CronTask[];
|
|
39
|
+
/**
|
|
40
|
+
* Remove a cron task by id.
|
|
41
|
+
* @returns true if the task existed and was removed
|
|
42
|
+
*/
|
|
43
|
+
export declare function removeCronTask(id: string, repoRoot?: string): boolean;
|
|
44
|
+
//# sourceMappingURL=cron.d.ts.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/agent/cron.ts
|
|
3
|
+
*
|
|
4
|
+
* Pillar A — Cron scheduled tasks.
|
|
5
|
+
*
|
|
6
|
+
* Exports:
|
|
7
|
+
* addCronTask({ cron, prompt, recurring })
|
|
8
|
+
* listCronTasks()
|
|
9
|
+
* removeCronTask(id)
|
|
10
|
+
*
|
|
11
|
+
* Persists to `.bizar/cron.json`.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { randomUUID } from "node:crypto";
|
|
16
|
+
function cronStorePath(repoRoot) {
|
|
17
|
+
return join(repoRoot ?? process.cwd(), ".bizar", "cron.json");
|
|
18
|
+
}
|
|
19
|
+
function loadStore(repoRoot) {
|
|
20
|
+
const fp = cronStorePath(repoRoot);
|
|
21
|
+
if (!existsSync(fp))
|
|
22
|
+
return { tasks: [] };
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(readFileSync(fp, "utf-8"));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return { tasks: [] };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function saveStore(store, repoRoot) {
|
|
31
|
+
const fp = cronStorePath(repoRoot);
|
|
32
|
+
const dir = join(fp, "..");
|
|
33
|
+
if (!existsSync(dir))
|
|
34
|
+
mkdirSync(dir, { recursive: true });
|
|
35
|
+
writeFileSync(fp, JSON.stringify(store, null, 2), "utf-8");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Add a cron task.
|
|
39
|
+
*
|
|
40
|
+
* @param opts.cron — cron expression (e.g. "0 * * * *")
|
|
41
|
+
* @param opts.prompt — prompt to execute on trigger
|
|
42
|
+
* @param opts.recurring — if false, task is removed after first run
|
|
43
|
+
* @param opts.repoRoot — optional repo root override
|
|
44
|
+
* @returns the created CronTask
|
|
45
|
+
*/
|
|
46
|
+
export function addCronTask(opts) {
|
|
47
|
+
const { cron, prompt, recurring = false, repoRoot } = opts;
|
|
48
|
+
const store = loadStore(repoRoot);
|
|
49
|
+
const task = {
|
|
50
|
+
id: randomUUID(),
|
|
51
|
+
cron,
|
|
52
|
+
prompt,
|
|
53
|
+
recurring,
|
|
54
|
+
createdAt: new Date().toISOString(),
|
|
55
|
+
};
|
|
56
|
+
store.tasks.push(task);
|
|
57
|
+
saveStore(store, repoRoot);
|
|
58
|
+
return task;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* List all cron tasks.
|
|
62
|
+
*/
|
|
63
|
+
export function listCronTasks(repoRoot) {
|
|
64
|
+
return loadStore(repoRoot).tasks;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Remove a cron task by id.
|
|
68
|
+
* @returns true if the task existed and was removed
|
|
69
|
+
*/
|
|
70
|
+
export function removeCronTask(id, repoRoot) {
|
|
71
|
+
const store = loadStore(repoRoot);
|
|
72
|
+
const before = store.tasks.length;
|
|
73
|
+
store.tasks = store.tasks.filter((t) => t.id !== id);
|
|
74
|
+
if (store.tasks.length === before)
|
|
75
|
+
return false;
|
|
76
|
+
saveStore(store, repoRoot);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=cron.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/agent/heartbeat.ts
|
|
3
|
+
*
|
|
4
|
+
* Pillar A — Heartbeat + session resume.
|
|
5
|
+
*
|
|
6
|
+
* Exports `startHeartbeat(intervalMs)` which returns a session ID and a
|
|
7
|
+
* JSONL writer that appends heartbeat records to
|
|
8
|
+
* `.harness/traces/heartbeat.jsonl`. Each record carries:
|
|
9
|
+
* session_id, started_at, last_heartbeat_at, status
|
|
10
|
+
*
|
|
11
|
+
* Status transitions: running → idle → done | failed
|
|
12
|
+
*/
|
|
13
|
+
export type SessionStatus = "running" | "idle" | "failed" | "done";
|
|
14
|
+
export interface HeartbeatRecord {
|
|
15
|
+
session_id: string;
|
|
16
|
+
started_at: string;
|
|
17
|
+
last_heartbeat_at: string;
|
|
18
|
+
status: SessionStatus;
|
|
19
|
+
}
|
|
20
|
+
/** Returns the path to the heartbeat log, resolved from repo root. */
|
|
21
|
+
export declare function heartbeatPath(repoRoot: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Start a heartbeat ticker.
|
|
24
|
+
*
|
|
25
|
+
* @param intervalMs — milliseconds between heartbeat writes (default 30_000)
|
|
26
|
+
* @param repoRoot — repository root (default process.cwd())
|
|
27
|
+
* @returns {{ sessionId: string, stop: () => void }}
|
|
28
|
+
*/
|
|
29
|
+
export declare function startHeartbeat(intervalMs?: number, repoRoot?: string): {
|
|
30
|
+
sessionId: string;
|
|
31
|
+
stop: () => void;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Mark a session as failed in the heartbeat log.
|
|
35
|
+
* Reads the original started_at from the JSONL file if available.
|
|
36
|
+
*/
|
|
37
|
+
export declare function failHeartbeat(sessionId: string, repoRoot?: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* Mark a session as done.
|
|
40
|
+
* Reads the original started_at from the JSONL file if available.
|
|
41
|
+
*/
|
|
42
|
+
export declare function stopHeartbeat(sessionId: string, repoRoot?: string): void;
|
|
43
|
+
//# sourceMappingURL=heartbeat.d.ts.map
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/agent/heartbeat.ts
|
|
3
|
+
*
|
|
4
|
+
* Pillar A — Heartbeat + session resume.
|
|
5
|
+
*
|
|
6
|
+
* Exports `startHeartbeat(intervalMs)` which returns a session ID and a
|
|
7
|
+
* JSONL writer that appends heartbeat records to
|
|
8
|
+
* `.harness/traces/heartbeat.jsonl`. Each record carries:
|
|
9
|
+
* session_id, started_at, last_heartbeat_at, status
|
|
10
|
+
*
|
|
11
|
+
* Status transitions: running → idle → done | failed
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, mkdirSync, appendFileSync, readFileSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { randomUUID } from "node:crypto";
|
|
16
|
+
/** Returns the path to the heartbeat log, resolved from repo root. */
|
|
17
|
+
export function heartbeatPath(repoRoot) {
|
|
18
|
+
return join(repoRoot, ".harness", "traces", "heartbeat.jsonl");
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Start a heartbeat ticker.
|
|
22
|
+
*
|
|
23
|
+
* @param intervalMs — milliseconds between heartbeat writes (default 30_000)
|
|
24
|
+
* @param repoRoot — repository root (default process.cwd())
|
|
25
|
+
* @returns {{ sessionId: string, stop: () => void }}
|
|
26
|
+
*/
|
|
27
|
+
export function startHeartbeat(intervalMs = 30_000, repoRoot) {
|
|
28
|
+
const root = repoRoot ?? process.cwd();
|
|
29
|
+
const dir = join(root, ".harness", "traces");
|
|
30
|
+
const fp = heartbeatPath(root);
|
|
31
|
+
if (!existsSync(dir)) {
|
|
32
|
+
mkdirSync(dir, { recursive: true });
|
|
33
|
+
}
|
|
34
|
+
const sessionId = randomUUID();
|
|
35
|
+
const startedAt = new Date().toISOString();
|
|
36
|
+
function writeRecord(status) {
|
|
37
|
+
const record = {
|
|
38
|
+
session_id: sessionId,
|
|
39
|
+
started_at: startedAt,
|
|
40
|
+
last_heartbeat_at: new Date().toISOString(),
|
|
41
|
+
status,
|
|
42
|
+
};
|
|
43
|
+
appendFileSync(fp, JSON.stringify(record) + "\n", "utf-8");
|
|
44
|
+
}
|
|
45
|
+
writeRecord("running");
|
|
46
|
+
const interval = setInterval(() => {
|
|
47
|
+
writeRecord("running");
|
|
48
|
+
}, intervalMs);
|
|
49
|
+
return {
|
|
50
|
+
sessionId,
|
|
51
|
+
stop: () => {
|
|
52
|
+
clearInterval(interval);
|
|
53
|
+
writeRecord("done");
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Mark a session as failed in the heartbeat log.
|
|
59
|
+
* Reads the original started_at from the JSONL file if available.
|
|
60
|
+
*/
|
|
61
|
+
export function failHeartbeat(sessionId, repoRoot) {
|
|
62
|
+
const root = repoRoot ?? process.cwd();
|
|
63
|
+
const fp = heartbeatPath(root);
|
|
64
|
+
if (!existsSync(fp))
|
|
65
|
+
return;
|
|
66
|
+
const startedAt = _readStartedAt(fp, sessionId);
|
|
67
|
+
const record = {
|
|
68
|
+
session_id: sessionId,
|
|
69
|
+
started_at: startedAt,
|
|
70
|
+
last_heartbeat_at: new Date().toISOString(),
|
|
71
|
+
status: "failed",
|
|
72
|
+
};
|
|
73
|
+
appendFileSync(fp, JSON.stringify(record) + "\n", "utf-8");
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Mark a session as done.
|
|
77
|
+
* Reads the original started_at from the JSONL file if available.
|
|
78
|
+
*/
|
|
79
|
+
export function stopHeartbeat(sessionId, repoRoot) {
|
|
80
|
+
const root = repoRoot ?? process.cwd();
|
|
81
|
+
const fp = heartbeatPath(root);
|
|
82
|
+
if (!existsSync(fp))
|
|
83
|
+
return;
|
|
84
|
+
const startedAt = _readStartedAt(fp, sessionId);
|
|
85
|
+
const record = {
|
|
86
|
+
session_id: sessionId,
|
|
87
|
+
started_at: startedAt,
|
|
88
|
+
last_heartbeat_at: new Date().toISOString(),
|
|
89
|
+
status: "done",
|
|
90
|
+
};
|
|
91
|
+
appendFileSync(fp, JSON.stringify(record) + "\n", "utf-8");
|
|
92
|
+
}
|
|
93
|
+
/** Find the original started_at for a session from the JSONL file. */
|
|
94
|
+
function _readStartedAt(fp, sessionId) {
|
|
95
|
+
try {
|
|
96
|
+
const raw = readFileSync(fp, "utf-8");
|
|
97
|
+
for (const line of raw.split("\n").reverse()) {
|
|
98
|
+
if (!line)
|
|
99
|
+
continue;
|
|
100
|
+
try {
|
|
101
|
+
const rec = JSON.parse(line);
|
|
102
|
+
if (rec.session_id === sessionId && rec.started_at) {
|
|
103
|
+
return rec.started_at;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// skip malformed lines
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// ignore read errors
|
|
113
|
+
}
|
|
114
|
+
return new Date().toISOString();
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -21,5 +21,8 @@ export { SwarmTopologyRegistry, swarmTopologyRegistry, initSwarm, getSwarm, list
|
|
|
21
21
|
export type { SwarmRecord, SwarmTopology, InitSwarmInput, InitSwarmResult, } from "./swarm-topology.js";
|
|
22
22
|
export { ByzantineConsensus, type ByzantineConsensusOpts, QueenCoordinator, type QueenCoordinatorOpts, createConsensus, getSharedConsensus, resetSharedConsensus, type ConsensusHandle, type CreateConsensusOpts, PHASE_ORDER, DEFAULT_QUORUM, DEFAULT_PEER_COUNT, DEFAULT_MAX_FAULTS, } from "./consensus/index.js";
|
|
23
23
|
export type { CommitResult, ConsensusOpts, ConsensusStatus, Decision, Phase, ProposeResult, Proposal, ProposalSnapshot, ProposalStatus, Vote, VoteResult, ViewChangeResult, } from "./consensus/types.js";
|
|
24
|
+
export { recordInstinct, listInstincts, promoteInstinct, dropInstinct, recordDecision, listDecisions, verifyChain, datamark, } from "./learning/index.js";
|
|
25
|
+
export { startHeartbeat, stopHeartbeat, failHeartbeat, heartbeatPath, type HeartbeatRecord, type SessionStatus, } from "./agent/heartbeat.js";
|
|
26
|
+
export { addCronTask, listCronTasks, removeCronTask, type CronTask, } from "./agent/cron.js";
|
|
24
27
|
export { SDK_VERSION } from "./version.js";
|
|
25
28
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -21,5 +21,10 @@ export { BizarAgentRegistry, bizarAgentRegistry, } from "./agent-registry.js";
|
|
|
21
21
|
export { SwarmTopologyRegistry, swarmTopologyRegistry, initSwarm, getSwarm, listSwarms, recordAgentInSwarm, decommissionSwarm, SWARM_TOPOLOGIES, DEFAULT_TOPOLOGY, DEFAULT_MAX_AGENTS, DEFAULT_SWARM_ID, } from "./swarm-topology.js";
|
|
22
22
|
// F-039 — Byzantine fault-tolerant consensus (thin PBFT port).
|
|
23
23
|
export { ByzantineConsensus, QueenCoordinator, createConsensus, getSharedConsensus, resetSharedConsensus, PHASE_ORDER, DEFAULT_QUORUM, DEFAULT_PEER_COUNT, DEFAULT_MAX_FAULTS, } from "./consensus/index.js";
|
|
24
|
+
// F-034 — Self-learning (Pillar D): instincts + decisions logs.
|
|
25
|
+
export { recordInstinct, listInstincts, promoteInstinct, dropInstinct, recordDecision, listDecisions, verifyChain, datamark, } from "./learning/index.js";
|
|
26
|
+
// Pillar A — heartbeat + cron (autonomous long-running agents)
|
|
27
|
+
export { startHeartbeat, stopHeartbeat, failHeartbeat, heartbeatPath, } from "./agent/heartbeat.js";
|
|
28
|
+
export { addCronTask, listCronTasks, removeCronTask, } from "./agent/cron.js";
|
|
24
29
|
export { SDK_VERSION } from "./version.js";
|
|
25
30
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* learning/decisions.ts — Decisions log (append-only, tamper-evident).
|
|
3
|
+
*
|
|
4
|
+
* v10.1.1 — Pillar D: Decisions log backed by `.bizar/learning/decisions.jsonl`.
|
|
5
|
+
*
|
|
6
|
+
* Each entry:
|
|
7
|
+
* {id, ts, event: 'decide'|'supersede'|'redact',
|
|
8
|
+
* subject, rationale, refs?, prev_hash, hash}
|
|
9
|
+
*
|
|
10
|
+
* tamper-evident chain: sha256(prev_hash + entry_body) → current hash.
|
|
11
|
+
* Datamark on render: escape unicode surrogates via JSON.stringify replacer
|
|
12
|
+
* (same pattern as gstack's wrapUntrustedContent).
|
|
13
|
+
*/
|
|
14
|
+
interface DecisionInput {
|
|
15
|
+
event: "decide" | "supersede" | "redact";
|
|
16
|
+
subject: string;
|
|
17
|
+
rationale: string;
|
|
18
|
+
refs?: string[];
|
|
19
|
+
project?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Record a new decision. Returns the created entry. */
|
|
22
|
+
export declare function recordDecision({ event, subject, rationale, refs, project, }: DecisionInput): Record<string, unknown>;
|
|
23
|
+
/** List all decisions. */
|
|
24
|
+
export declare function listDecisions(opts?: {
|
|
25
|
+
project?: string;
|
|
26
|
+
}): Record<string, unknown>[];
|
|
27
|
+
/**
|
|
28
|
+
* Verify the tamper-evident chain.
|
|
29
|
+
* Returns { ok: true } if every entry's hash matches the computed hash
|
|
30
|
+
* and prev_hash chains correctly. Returns { ok: false, at: number } on
|
|
31
|
+
* the first break.
|
|
32
|
+
*/
|
|
33
|
+
export declare function verifyChain(opts?: {
|
|
34
|
+
project?: string;
|
|
35
|
+
}): {
|
|
36
|
+
ok: boolean;
|
|
37
|
+
at?: number;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Datamark renderer — escape unicode surrogates so JSON.stringify never
|
|
41
|
+
* emits invalid strings when rendering decisions in the UI.
|
|
42
|
+
* Pattern borrowed from gstack's wrapUntrustedContent.
|
|
43
|
+
*/
|
|
44
|
+
export declare function datamark(value: unknown): unknown;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=decisions.d.ts.map
|