@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.
Files changed (223) hide show
  1. package/README.md +0 -2
  2. package/bizar-dash/dist/assets/{ActivityFeed-Da-JCrE6.js → ActivityFeed-JjmOY2AQ.js} +1 -1
  3. package/bizar-dash/dist/assets/{ActivityFeed-Da-JCrE6.js.map → ActivityFeed-JjmOY2AQ.js.map} +1 -1
  4. package/bizar-dash/dist/assets/{ActivityView-nIRsSETb.js → ActivityView-BIIMvGWo.js} +1 -1
  5. package/bizar-dash/dist/assets/{ActivityView-nIRsSETb.js.map → ActivityView-BIIMvGWo.js.map} +1 -1
  6. package/bizar-dash/dist/assets/{AdminView-DP1NMxmG.js → AdminView-DRidJtkq.js} +1 -1
  7. package/bizar-dash/dist/assets/{AdminView-DP1NMxmG.js.map → AdminView-DRidJtkq.js.map} +1 -1
  8. package/bizar-dash/dist/assets/{AgentActivity-lSPkOr-O.js → AgentActivity-79l4SBMC.js} +1 -1
  9. package/bizar-dash/dist/assets/{AgentActivity-lSPkOr-O.js.map → AgentActivity-79l4SBMC.js.map} +1 -1
  10. package/bizar-dash/dist/assets/{AgentsView-BIWGkz7w.js → AgentsView-0vT4uPSc.js} +1 -1
  11. package/bizar-dash/dist/assets/{AgentsView-BIWGkz7w.js.map → AgentsView-0vT4uPSc.js.map} +1 -1
  12. package/bizar-dash/dist/assets/{Alert-DN0UysMg.js → Alert-CG5q_s75.js} +1 -1
  13. package/bizar-dash/dist/assets/{Alert-DN0UysMg.js.map → Alert-CG5q_s75.js.map} +1 -1
  14. package/bizar-dash/dist/assets/ArtifactsView-DM8ZmpR9.js +21 -0
  15. package/bizar-dash/dist/assets/ArtifactsView-DM8ZmpR9.js.map +1 -0
  16. package/bizar-dash/dist/assets/{AuthView-DW5cs7ma.js → AuthView-BveN94MC.js} +1 -1
  17. package/bizar-dash/dist/assets/{AuthView-DW5cs7ma.js.map → AuthView-BveN94MC.js.map} +1 -1
  18. package/bizar-dash/dist/assets/{Avatar-DZPv9pvd.js → Avatar-ulUPIYTd.js} +1 -1
  19. package/bizar-dash/dist/assets/{Avatar-DZPv9pvd.js.map → Avatar-ulUPIYTd.js.map} +1 -1
  20. package/bizar-dash/dist/assets/{BackgroundJobsView-D8O-EyMD.js → BackgroundJobsView-BWErhqFo.js} +1 -1
  21. package/bizar-dash/dist/assets/{BackgroundJobsView-D8O-EyMD.js.map → BackgroundJobsView-BWErhqFo.js.map} +1 -1
  22. package/bizar-dash/dist/assets/{BackupView-uwXkhxOV.js → BackupView-CnBjzG9N.js} +1 -1
  23. package/bizar-dash/dist/assets/{BackupView-uwXkhxOV.js.map → BackupView-CnBjzG9N.js.map} +1 -1
  24. package/bizar-dash/dist/assets/{Card-Tyboihu7.js → Card-B0imhxMk.js} +1 -1
  25. package/bizar-dash/dist/assets/{Card-Tyboihu7.js.map → Card-B0imhxMk.js.map} +1 -1
  26. package/bizar-dash/dist/assets/{ChatView-DRBHzgay.js → ChatView-D6zGytzx.js} +1 -1
  27. package/bizar-dash/dist/assets/{ChatView-DRBHzgay.js.map → ChatView-D6zGytzx.js.map} +1 -1
  28. package/bizar-dash/dist/assets/{Chip-BrXIlR9w.js → Chip-wwZSGwLE.js} +1 -1
  29. package/bizar-dash/dist/assets/{Chip-BrXIlR9w.js.map → Chip-wwZSGwLE.js.map} +1 -1
  30. package/bizar-dash/dist/assets/{ClaudeSessionsView-Ck62jaOr.js → ClaudeSessionsView-DK1sOLhi.js} +1 -1
  31. package/bizar-dash/dist/assets/{ClaudeSessionsView-Ck62jaOr.js.map → ClaudeSessionsView-DK1sOLhi.js.map} +1 -1
  32. package/bizar-dash/dist/assets/{ClipboardView-DfND6xL6.js → ClipboardView-CZ2lYPr0.js} +1 -1
  33. package/bizar-dash/dist/assets/{ClipboardView-DfND6xL6.js.map → ClipboardView-CZ2lYPr0.js.map} +1 -1
  34. package/bizar-dash/dist/assets/{ConfigView-DjJmSrOJ.js → ConfigView-D-zT9eNA.js} +1 -1
  35. package/bizar-dash/dist/assets/{ConfigView-DjJmSrOJ.js.map → ConfigView-D-zT9eNA.js.map} +1 -1
  36. package/bizar-dash/dist/assets/{DiagnosticsView-CKgItf0J.js → DiagnosticsView-BocV68Lb.js} +1 -1
  37. package/bizar-dash/dist/assets/{DiagnosticsView-CKgItf0J.js.map → DiagnosticsView-BocV68Lb.js.map} +1 -1
  38. package/bizar-dash/dist/assets/{DialogsView-DHYF8dE1.js → DialogsView-BVjPI5x7.js} +1 -1
  39. package/bizar-dash/dist/assets/{DialogsView-DHYF8dE1.js.map → DialogsView-BVjPI5x7.js.map} +1 -1
  40. package/bizar-dash/dist/assets/{DoctorView-DDLHrSKk.js → DoctorView-84gJcZwM.js} +1 -1
  41. package/bizar-dash/dist/assets/{DoctorView-DDLHrSKk.js.map → DoctorView-84gJcZwM.js.map} +1 -1
  42. package/bizar-dash/dist/assets/{EmptyState-DZ2ouKwd.js → EmptyState-BjgVOrcO.js} +1 -1
  43. package/bizar-dash/dist/assets/{EmptyState-DZ2ouKwd.js.map → EmptyState-BjgVOrcO.js.map} +1 -1
  44. package/bizar-dash/dist/assets/{EnvVarsView-D1cx83mB.js → EnvVarsView-BJ2TEzF7.js} +1 -1
  45. package/bizar-dash/dist/assets/{EnvVarsView-D1cx83mB.js.map → EnvVarsView-BJ2TEzF7.js.map} +1 -1
  46. package/bizar-dash/dist/assets/{ErrorState-DwwJ2-Jq.js → ErrorState-BE3WBFqF.js} +1 -1
  47. package/bizar-dash/dist/assets/{ErrorState-DwwJ2-Jq.js.map → ErrorState-BE3WBFqF.js.map} +1 -1
  48. package/bizar-dash/dist/assets/{EvalView-C9aYixXW.js → EvalView-BJJ2P-kK.js} +1 -1
  49. package/bizar-dash/dist/assets/{EvalView-C9aYixXW.js.map → EvalView-BJJ2P-kK.js.map} +1 -1
  50. package/bizar-dash/dist/assets/{GoalsView-DZa_mGmh.js → GoalsView-pwROHApi.js} +1 -1
  51. package/bizar-dash/dist/assets/{GoalsView-DZa_mGmh.js.map → GoalsView-pwROHApi.js.map} +1 -1
  52. package/bizar-dash/dist/assets/{Grid-CiRyhAgR.js → Grid-qcvbhx6e.js} +1 -1
  53. package/bizar-dash/dist/assets/{Grid-CiRyhAgR.js.map → Grid-qcvbhx6e.js.map} +1 -1
  54. package/bizar-dash/dist/assets/{HeadroomView-CNc-TI7u.js → HeadroomView-D1UiTYbt.js} +1 -1
  55. package/bizar-dash/dist/assets/{HeadroomView-CNc-TI7u.js.map → HeadroomView-D1UiTYbt.js.map} +1 -1
  56. package/bizar-dash/dist/assets/{HistoryView-Dv7aPxJE.js → HistoryView-C7SSOLJA.js} +1 -1
  57. package/bizar-dash/dist/assets/{HistoryView-Dv7aPxJE.js.map → HistoryView-C7SSOLJA.js.map} +1 -1
  58. package/bizar-dash/dist/assets/{Input-BbFUDQnS.js → Input-Bgzxf_Hu.js} +1 -1
  59. package/bizar-dash/dist/assets/{Input-BbFUDQnS.js.map → Input-Bgzxf_Hu.js.map} +1 -1
  60. package/bizar-dash/dist/assets/{LibrariesView-DBQ83TNa.js → LibrariesView-CbFFksox.js} +1 -1
  61. package/bizar-dash/dist/assets/{LibrariesView-DBQ83TNa.js.map → LibrariesView-CbFFksox.js.map} +1 -1
  62. package/bizar-dash/dist/assets/{LightRAGView-JYpE5u9p.js → LightRAGView-BqDrJbRq.js} +1 -1
  63. package/bizar-dash/dist/assets/{LightRAGView-JYpE5u9p.js.map → LightRAGView-BqDrJbRq.js.map} +1 -1
  64. package/bizar-dash/dist/assets/{ListHeader-BGjm11Z0.js → ListHeader-TjPJrUfY.js} +1 -1
  65. package/bizar-dash/dist/assets/{ListHeader-BGjm11Z0.js.map → ListHeader-TjPJrUfY.js.map} +1 -1
  66. package/bizar-dash/dist/assets/{MemoryView-CnOP2MvM.js → MemoryView-BlTeHLhX.js} +1 -1
  67. package/bizar-dash/dist/assets/{MemoryView-CnOP2MvM.js.map → MemoryView-BlTeHLhX.js.map} +1 -1
  68. package/bizar-dash/dist/assets/{MiscView-BBcpUbZZ.js → MiscView-B8QY82Pm.js} +1 -1
  69. package/bizar-dash/dist/assets/{MiscView-BBcpUbZZ.js.map → MiscView-B8QY82Pm.js.map} +1 -1
  70. package/bizar-dash/dist/assets/{ModsView-CU4cAmIz.js → ModsView-CvW1OWts.js} +1 -1
  71. package/bizar-dash/dist/assets/{ModsView-CU4cAmIz.js.map → ModsView-CvW1OWts.js.map} +1 -1
  72. package/bizar-dash/dist/assets/{NotificationsView-BYffvthq.js → NotificationsView-CsBt5U7x.js} +1 -1
  73. package/bizar-dash/dist/assets/{NotificationsView-BYffvthq.js.map → NotificationsView-CsBt5U7x.js.map} +1 -1
  74. package/bizar-dash/dist/assets/{ObsidianView-D3bI0row.js → ObsidianView-BCTejEj2.js} +1 -1
  75. package/bizar-dash/dist/assets/{ObsidianView-D3bI0row.js.map → ObsidianView-BCTejEj2.js.map} +1 -1
  76. package/bizar-dash/dist/assets/{OverviewView-0tq8f-Y0.js → OverviewView-BsuPxwnB.js} +1 -1
  77. package/bizar-dash/dist/assets/{OverviewView-0tq8f-Y0.js.map → OverviewView-BsuPxwnB.js.map} +1 -1
  78. package/bizar-dash/dist/assets/{ProgressBar-B-h60LKA.js → ProgressBar-DlZTETEn.js} +1 -1
  79. package/bizar-dash/dist/assets/{ProgressBar-B-h60LKA.js.map → ProgressBar-DlZTETEn.js.map} +1 -1
  80. package/bizar-dash/dist/assets/{ProjectsView-DhX5lzHS.js → ProjectsView-Soxtmpet.js} +1 -1
  81. package/bizar-dash/dist/assets/{ProjectsView-DhX5lzHS.js.map → ProjectsView-Soxtmpet.js.map} +1 -1
  82. package/bizar-dash/dist/assets/{ProvidersView-CJMX7jm9.js → ProvidersView-DaCEV9pM.js} +1 -1
  83. package/bizar-dash/dist/assets/{ProvidersView-CJMX7jm9.js.map → ProvidersView-DaCEV9pM.js.map} +1 -1
  84. package/bizar-dash/dist/assets/{SchedulesView-CcwDQ9Nm.js → SchedulesView-DY2ByBj_.js} +1 -1
  85. package/bizar-dash/dist/assets/{SchedulesView-CcwDQ9Nm.js.map → SchedulesView-DY2ByBj_.js.map} +1 -1
  86. package/bizar-dash/dist/assets/{Select-Cw7Qtz2M.js → Select-Dbd88_n8.js} +1 -1
  87. package/bizar-dash/dist/assets/{Select-Cw7Qtz2M.js.map → Select-Dbd88_n8.js.map} +1 -1
  88. package/bizar-dash/dist/assets/{SettingsRow-DgsgbPSI.js → SettingsRow-CLMNd434.js} +1 -1
  89. package/bizar-dash/dist/assets/{SettingsRow-DgsgbPSI.js.map → SettingsRow-CLMNd434.js.map} +1 -1
  90. package/bizar-dash/dist/assets/{SettingsView-DTAFdKyK.js → SettingsView-b24oFq9x.js} +1 -1
  91. package/bizar-dash/dist/assets/{SettingsView-DTAFdKyK.js.map → SettingsView-b24oFq9x.js.map} +1 -1
  92. package/bizar-dash/dist/assets/{Sheet-DH-WNJ3Y.js → Sheet-DnDid58j.js} +1 -1
  93. package/bizar-dash/dist/assets/{Sheet-DH-WNJ3Y.js.map → Sheet-DnDid58j.js.map} +1 -1
  94. package/bizar-dash/dist/assets/{Slider-DXbJuQ7y.js → Slider-BJCvKI1I.js} +1 -1
  95. package/bizar-dash/dist/assets/{Slider-DXbJuQ7y.js.map → Slider-BJCvKI1I.js.map} +1 -1
  96. package/bizar-dash/dist/assets/{Sparkline-CYtAn82j.js → Sparkline-ktqQLdyb.js} +1 -1
  97. package/bizar-dash/dist/assets/{Sparkline-CYtAn82j.js.map → Sparkline-ktqQLdyb.js.map} +1 -1
  98. package/bizar-dash/dist/assets/{Switch-BItGrPqr.js → Switch-CwXfsDii.js} +1 -1
  99. package/bizar-dash/dist/assets/{Switch-BItGrPqr.js.map → Switch-CwXfsDii.js.map} +1 -1
  100. package/bizar-dash/dist/assets/{TasksView-i5tm6CkX.js → TasksView-BHmpzFCf.js} +1 -1
  101. package/bizar-dash/dist/assets/{TasksView-i5tm6CkX.js.map → TasksView-BHmpzFCf.js.map} +1 -1
  102. package/bizar-dash/dist/assets/{Textarea-qYDf3yds.js → Textarea-BzIAwSlp.js} +1 -1
  103. package/bizar-dash/dist/assets/{Textarea-qYDf3yds.js.map → Textarea-BzIAwSlp.js.map} +1 -1
  104. package/bizar-dash/dist/assets/{UpdateView-Xln-ej26.js → UpdateView-CSmX9NN0.js} +1 -1
  105. package/bizar-dash/dist/assets/{UpdateView-Xln-ej26.js.map → UpdateView-CSmX9NN0.js.map} +1 -1
  106. package/bizar-dash/dist/assets/{UsageView-BGuZSUZ6.js → UsageView-COyr_Gfi.js} +1 -1
  107. package/bizar-dash/dist/assets/{UsageView-BGuZSUZ6.js.map → UsageView-COyr_Gfi.js.map} +1 -1
  108. package/bizar-dash/dist/assets/{ViewHeader-BqIPVKuG.js → ViewHeader-BzYZ3m-e.js} +1 -1
  109. package/bizar-dash/dist/assets/{ViewHeader-BqIPVKuG.js.map → ViewHeader-BzYZ3m-e.js.map} +1 -1
  110. package/bizar-dash/dist/assets/{VoiceView-CWUOCQs_.js → VoiceView-D33_xG5t.js} +1 -1
  111. package/bizar-dash/dist/assets/{VoiceView-CWUOCQs_.js.map → VoiceView-D33_xG5t.js.map} +1 -1
  112. package/bizar-dash/dist/assets/{brain-fsBSDl2g.js → brain-CM-Vls8r.js} +1 -1
  113. package/bizar-dash/dist/assets/{brain-fsBSDl2g.js.map → brain-CM-Vls8r.js.map} +1 -1
  114. package/bizar-dash/dist/assets/{calendar-DsHTZoCU.js → calendar-C0lgZk69.js} +1 -1
  115. package/bizar-dash/dist/assets/{calendar-DsHTZoCU.js.map → calendar-C0lgZk69.js.map} +1 -1
  116. package/bizar-dash/dist/assets/{circle-CqSxqqeJ.js → circle-Bx_hQEBC.js} +1 -1
  117. package/bizar-dash/dist/assets/{circle-CqSxqqeJ.js.map → circle-Bx_hQEBC.js.map} +1 -1
  118. package/bizar-dash/dist/assets/{circle-alert-BsLl001l.js → circle-alert-DHvsqpw5.js} +1 -1
  119. package/bizar-dash/dist/assets/{circle-alert-BsLl001l.js.map → circle-alert-DHvsqpw5.js.map} +1 -1
  120. package/bizar-dash/dist/assets/{circle-check-rVKMQmZp.js → circle-check-Bx8wmXR9.js} +1 -1
  121. package/bizar-dash/dist/assets/{circle-check-rVKMQmZp.js.map → circle-check-Bx8wmXR9.js.map} +1 -1
  122. package/bizar-dash/dist/assets/{clock-OuficfgH.js → clock-CejGoecX.js} +1 -1
  123. package/bizar-dash/dist/assets/{clock-OuficfgH.js.map → clock-CejGoecX.js.map} +1 -1
  124. package/bizar-dash/dist/assets/{download-BdHlstUY.js → download-4cEUWue1.js} +1 -1
  125. package/bizar-dash/dist/assets/{download-BdHlstUY.js.map → download-4cEUWue1.js.map} +1 -1
  126. package/bizar-dash/dist/assets/{external-link-DA3_VGm-.js → external-link-0NqUhI4i.js} +1 -1
  127. package/bizar-dash/dist/assets/{external-link-DA3_VGm-.js.map → external-link-0NqUhI4i.js.map} +1 -1
  128. package/bizar-dash/dist/assets/{file-text-B-g8H227.js → file-text-yEMkrSoZ.js} +1 -1
  129. package/bizar-dash/dist/assets/{file-text-B-g8H227.js.map → file-text-yEMkrSoZ.js.map} +1 -1
  130. package/bizar-dash/dist/assets/{filter-D9B8s5CG.js → filter-BXt60zAS.js} +1 -1
  131. package/bizar-dash/dist/assets/{filter-D9B8s5CG.js.map → filter-BXt60zAS.js.map} +1 -1
  132. package/bizar-dash/dist/assets/{git-pull-request-ByH0YuVz.js → git-pull-request-BjG5lNtR.js} +1 -1
  133. package/bizar-dash/dist/assets/{git-pull-request-ByH0YuVz.js.map → git-pull-request-BjG5lNtR.js.map} +1 -1
  134. package/bizar-dash/dist/assets/{main-CdOm1Pj9.js → main-CokHAXWM.js} +2 -2
  135. package/bizar-dash/dist/assets/{main-CdOm1Pj9.js.map → main-CokHAXWM.js.map} +1 -1
  136. package/bizar-dash/dist/assets/{pause-C9hgd8wX.js → pause-CAmulU0F.js} +1 -1
  137. package/bizar-dash/dist/assets/{pause-C9hgd8wX.js.map → pause-CAmulU0F.js.map} +1 -1
  138. package/bizar-dash/dist/assets/{pencil-BanqaMw7.js → pencil-eq5IqBmU.js} +1 -1
  139. package/bizar-dash/dist/assets/{pencil-BanqaMw7.js.map → pencil-eq5IqBmU.js.map} +1 -1
  140. package/bizar-dash/dist/assets/{play-CawUZ02_.js → play-BoLrrcBA.js} +1 -1
  141. package/bizar-dash/dist/assets/{play-CawUZ02_.js.map → play-BoLrrcBA.js.map} +1 -1
  142. package/bizar-dash/dist/assets/{plug-Cmv0-T_e.js → plug-DBrVM9lK.js} +1 -1
  143. package/bizar-dash/dist/assets/{plug-Cmv0-T_e.js.map → plug-DBrVM9lK.js.map} +1 -1
  144. package/bizar-dash/dist/assets/{plus-M6LYiKX8.js → plus-DENm0hqV.js} +1 -1
  145. package/bizar-dash/dist/assets/{plus-M6LYiKX8.js.map → plus-DENm0hqV.js.map} +1 -1
  146. package/bizar-dash/dist/assets/{power-DP5x_SRF.js → power-DLjXF7zE.js} +1 -1
  147. package/bizar-dash/dist/assets/{power-DP5x_SRF.js.map → power-DLjXF7zE.js.map} +1 -1
  148. package/bizar-dash/dist/assets/{power-off-NOJRLAIs.js → power-off-D47cOnG_.js} +1 -1
  149. package/bizar-dash/dist/assets/{power-off-NOJRLAIs.js.map → power-off-D47cOnG_.js.map} +1 -1
  150. package/bizar-dash/dist/assets/{refresh-ccw-CHMprsm5.js → refresh-ccw-DNrXX9gB.js} +1 -1
  151. package/bizar-dash/dist/assets/{refresh-ccw-CHMprsm5.js.map → refresh-ccw-DNrXX9gB.js.map} +1 -1
  152. package/bizar-dash/dist/assets/{refresh-cw-1RBqDKgJ.js → refresh-cw-CoAHDpeS.js} +1 -1
  153. package/bizar-dash/dist/assets/{refresh-cw-1RBqDKgJ.js.map → refresh-cw-CoAHDpeS.js.map} +1 -1
  154. package/bizar-dash/dist/assets/{rotate-ccw-DJRekBbi.js → rotate-ccw-ObX5awaG.js} +1 -1
  155. package/bizar-dash/dist/assets/{rotate-ccw-DJRekBbi.js.map → rotate-ccw-ObX5awaG.js.map} +1 -1
  156. package/bizar-dash/dist/assets/{rotate-cw-DHooc0Tx.js → rotate-cw-xpPJw9LP.js} +1 -1
  157. package/bizar-dash/dist/assets/{rotate-cw-DHooc0Tx.js.map → rotate-cw-xpPJw9LP.js.map} +1 -1
  158. package/bizar-dash/dist/assets/{save-DQKCKyZK.js → save-D1iKiJJl.js} +1 -1
  159. package/bizar-dash/dist/assets/{save-DQKCKyZK.js.map → save-D1iKiJJl.js.map} +1 -1
  160. package/bizar-dash/dist/assets/{send-xgy3RAi7.js → send-BRcAhZUm.js} +1 -1
  161. package/bizar-dash/dist/assets/{send-xgy3RAi7.js.map → send-BRcAhZUm.js.map} +1 -1
  162. package/bizar-dash/dist/assets/{shield-alert-CWV2F5ab.js → shield-alert-C6vEcK-g.js} +1 -1
  163. package/bizar-dash/dist/assets/{shield-alert-CWV2F5ab.js.map → shield-alert-C6vEcK-g.js.map} +1 -1
  164. package/bizar-dash/dist/assets/{trash-2-CL4khSRv.js → trash-2-DZDjEnNh.js} +1 -1
  165. package/bizar-dash/dist/assets/{trash-2-CL4khSRv.js.map → trash-2-DZDjEnNh.js.map} +1 -1
  166. package/bizar-dash/dist/assets/{trending-up-CSJJhWTS.js → trending-up-DMj-AJVf.js} +1 -1
  167. package/bizar-dash/dist/assets/{trending-up-CSJJhWTS.js.map → trending-up-DMj-AJVf.js.map} +1 -1
  168. package/bizar-dash/dist/assets/{triangle-alert-BPLb7uLt.js → triangle-alert-_2xe_tl4.js} +1 -1
  169. package/bizar-dash/dist/assets/{triangle-alert-BPLb7uLt.js.map → triangle-alert-_2xe_tl4.js.map} +1 -1
  170. package/bizar-dash/dist/assets/{upload-Cww6MvFq.js → upload-DdDljAeV.js} +1 -1
  171. package/bizar-dash/dist/assets/{upload-Cww6MvFq.js.map → upload-DdDljAeV.js.map} +1 -1
  172. package/bizar-dash/dist/assets/{zap-DmhVUzRA.js → zap-mHsgh0FP.js} +1 -1
  173. package/bizar-dash/dist/assets/{zap-DmhVUzRA.js.map → zap-mHsgh0FP.js.map} +1 -1
  174. package/bizar-dash/dist/index.html +1 -1
  175. package/bizar-dash/skills/headroom/SKILL.md +94 -0
  176. package/bizar-dash/src/server/api.mjs +11 -0
  177. package/bizar-dash/src/server/artifacts-store.mjs +120 -14
  178. package/bizar-dash/src/server/claude-artifacts.mjs +281 -0
  179. package/bizar-dash/src/server/headroom.mjs +649 -0
  180. package/bizar-dash/src/server/routes/artifacts.mjs +42 -6
  181. package/bizar-dash/src/server/routes/audit.mjs +78 -0
  182. package/bizar-dash/src/server/routes/decisions.mjs +78 -0
  183. package/bizar-dash/src/server/routes/headroom.mjs +126 -0
  184. package/bizar-dash/src/server/routes/model-router.mjs +55 -0
  185. package/bizar-dash/src/server/routes/model-router.test.mjs +28 -0
  186. package/bizar-dash/src/server/routes/sessions.mjs +80 -0
  187. package/bizar-dash/src/server/sprint.test.mjs +163 -0
  188. package/bizar-dash/src/web/v8/views/Artifacts/ArtifactsView.tsx +232 -21
  189. package/bizar-dash/src/web/v8/views/Artifacts/ClaudeArtifactView.tsx +179 -0
  190. package/bizar-dash/tests/headroom-install.test.mjs +173 -0
  191. package/bizar-dash/tests/headroom-settings.test.mjs +126 -0
  192. package/bizar-dash/tests/headroom-status.test.mjs +117 -0
  193. package/cli/commands/headroom.mjs +204 -0
  194. package/package.json +1 -1
  195. package/packages/sdk/dist/agent/cron.d.ts +44 -0
  196. package/packages/sdk/dist/agent/cron.js +79 -0
  197. package/packages/sdk/dist/agent/heartbeat.d.ts +43 -0
  198. package/packages/sdk/dist/agent/heartbeat.js +116 -0
  199. package/packages/sdk/dist/index.d.ts +3 -0
  200. package/packages/sdk/dist/index.js +5 -0
  201. package/packages/sdk/dist/learning/decisions.d.ts +46 -0
  202. package/packages/sdk/dist/learning/decisions.js +132 -0
  203. package/packages/sdk/dist/learning/index.d.ts +8 -0
  204. package/packages/sdk/dist/learning/index.js +8 -0
  205. package/packages/sdk/dist/learning/instincts.d.ts +38 -0
  206. package/packages/sdk/dist/learning/instincts.js +139 -0
  207. package/packages/sdk/dist/mcp/server.js +119 -1
  208. package/packages/sdk/dist/router/agent-model-registry.d.ts +89 -0
  209. package/packages/sdk/dist/router/agent-model-registry.js +144 -0
  210. package/packages/sdk/dist/router/index.d.ts +1 -0
  211. package/packages/sdk/dist/router/index.js +1 -0
  212. package/packages/sdk/package.json +3 -2
  213. package/scripts/audit.mjs +388 -0
  214. package/scripts/audit.test.mjs +149 -0
  215. package/scripts/eval-gate.mjs +134 -0
  216. package/scripts/eval-gate.test.mjs +138 -0
  217. package/scripts/feature-state-machine.mjs +178 -0
  218. package/scripts/feature-state-machine.test.mjs +135 -0
  219. package/scripts/spec-dedup.test.mjs +124 -0
  220. package/scripts/sprint.mjs +213 -0
  221. package/scripts/worktree-setup.sh +79 -0
  222. package/bizar-dash/dist/assets/ArtifactsView-CDIhPBAx.js +0 -6
  223. package/bizar-dash/dist/assets/ArtifactsView-CDIhPBAx.js.map +0 -1
@@ -51,18 +51,54 @@ export function createArtifactsRouter({ state, broadcast, projectRoot }) {
51
51
  res.json(artifact);
52
52
  }));
53
53
 
54
- // v3.21.0 — Compile the artifact's MDX into a JSON-serializable
55
- // glyph structure for the new Glyphs renderer. Returns frontmatter
56
- // + a flat list of typed blocks, ready for the client-side block
57
- // component map to render.
54
+ // v3.21.0 — Compile the artifact for the renderer. Dispatches by kind:
55
+ // mdx → JSON glyph blocks (legacy v3-v9 renderer)
56
+ // claude-html → iframe-ready HTML envelope
57
+ // claude-svg → iframe-ready HTML envelope (SVG body)
58
+ // claude-react → iframe-ready HTML envelope (Babel-standalone JSX)
59
+ // The Claude-* envelope is ready to drop into an iframe `srcdoc`; the
60
+ // client previewer component (`<ClaudeArtifactView>`) picks the
61
+ // correct renderer based on `kind` and `html`.
58
62
  router.get('/artifacts/:slug/render', wrap(async (req, res) => {
59
63
  const artifact = artifactsStore.get(req.params.slug, projectRoot);
60
64
  if (!artifact) {
61
65
  res.status(404).json({ error: 'not_found' });
62
66
  return;
63
67
  }
64
- const compiled = await compileGlyphMdx(artifact.planMdx || '');
65
- res.json({ slug: req.params.slug, ...compiled });
68
+ const kind = artifact.kind || 'mdx';
69
+ if (kind === 'mdx') {
70
+ const compiled = await compileGlyphMdx(artifact.planMdx || '');
71
+ res.json({ slug: req.params.slug, kind, ...compiled });
72
+ return;
73
+ }
74
+ const compiled = artifactsStore.compile(req.params.slug, projectRoot);
75
+ if (!compiled) {
76
+ res.status(404).json({ error: 'not_found' });
77
+ return;
78
+ }
79
+ res.json({
80
+ slug: req.params.slug,
81
+ kind: compiled.kind,
82
+ html: compiled.html,
83
+ warnings: compiled.warnings || [],
84
+ safeMode: !!compiled.safeMode,
85
+ compiledAt: compiled.compiledAt,
86
+ });
87
+ }));
88
+
89
+ // v10.1.0 — Full-screen viewer. Returns the compiled HTML envelope
90
+ // with `Content-Type: text/html` so a `<a target="_blank">` opens
91
+ // the artifact on its own page (no dashboard chrome). The iframe
92
+ // `sandbox` rules from the envelope apply — the page is just the
93
+ // envelope served as `text/html`.
94
+ router.get('/artifacts/:slug/view', wrap(async (req, res) => {
95
+ const compiled = artifactsStore.compile(req.params.slug, projectRoot);
96
+ if (!compiled) {
97
+ res.status(404).type('html').send('<h1>Not found</h1>');
98
+ return;
99
+ }
100
+ res.set('Content-Security-Policy', "default-src 'self'; script-src 'unsafe-inline' 'unsafe-eval' https://unpkg.com https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src * data:;");
101
+ res.type('html').send(compiled.html);
66
102
  }));
67
103
 
68
104
  // v3.1.0 — Full artifact CRUD + canvas editing.
@@ -0,0 +1,78 @@
1
+ /**
2
+ * src/server/routes/audit.mjs
3
+ *
4
+ * GET /api/audit — returns latest harness audit score + diff vs prior.
5
+ *
6
+ * Reads .harness/audit/latest.json (written by `node scripts/audit.mjs --write`).
7
+ * Returns the full audit result plus a `diff` object showing which categories
8
+ * changed score vs the prior run (if any).
9
+ */
10
+ import { existsSync, readFileSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { wrap } from './_shared.mjs';
13
+
14
+ /**
15
+ * @param {object} deps
16
+ * @param {string} deps.projectRoot
17
+ * @returns {import('express').Router}
18
+ */
19
+ export function createAuditRouter({ projectRoot }) {
20
+ const router = require('express').Router();
21
+ const LATEST = join(projectRoot, '.harness', 'audit', 'latest.json');
22
+
23
+ router.get('/audit', wrap(async (_req, res) => {
24
+ if (!existsSync(LATEST)) {
25
+ res.status(404).json({
26
+ error: 'not_ready',
27
+ message: 'No audit run yet. Run `node scripts/audit.mjs --write` first.',
28
+ });
29
+ return;
30
+ }
31
+
32
+ let latest;
33
+ try {
34
+ latest = JSON.parse(readFileSync(LATEST, 'utf8'));
35
+ } catch (err) {
36
+ res.status(500).json({ error: 'parse_error', message: err.message });
37
+ return;
38
+ }
39
+
40
+ // Compute diff vs the run before last (if we have history)
41
+ /** @type {Record<string, {current: number, prior: number, delta: number} | null>} */
42
+ const diff = {};
43
+ const priorPath = join(projectRoot, '.harness', 'audit', 'previous.json');
44
+
45
+ if (existsSync(priorPath)) {
46
+ try {
47
+ const prior = JSON.parse(readFileSync(priorPath, 'utf8'));
48
+ const priorScores = prior.scores ?? {};
49
+ for (const [key, weight] of Object.entries(latest.weights ?? {})) {
50
+ const current = latest.scores?.[key] ?? 0;
51
+ const priorScore = priorScores[key] ?? 0;
52
+ if (current !== priorScore) {
53
+ diff[key] = { current, prior: priorScore, delta: current - priorScore };
54
+ }
55
+ }
56
+ // Also diff total
57
+ const currentTotal = latest.total ?? 0;
58
+ const priorTotal = prior.total ?? 0;
59
+ if (currentTotal !== priorTotal) {
60
+ diff._total = { current: currentTotal, prior: priorTotal, delta: currentTotal - priorTotal };
61
+ }
62
+ } catch {
63
+ // prior file unreadable — no diff
64
+ }
65
+ }
66
+
67
+ res.json({
68
+ latest,
69
+ diff,
70
+ _links: {
71
+ run: 'node scripts/audit.mjs --write',
72
+ latestPath: LATEST,
73
+ },
74
+ });
75
+ }));
76
+
77
+ return router;
78
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * src/server/routes/decisions.mjs
3
+ *
4
+ * v10.1.1 — Pillar D: Decisions log API.
5
+ *
6
+ * GET /api/decisions
7
+ * Returns list of decisions + tamper-evidence status.
8
+ *
9
+ * Storage: <projectRoot>/.bizar/learning/decisions.jsonl
10
+ * Falls back to BIZAR_HOME if projectRoot is not set.
11
+ */
12
+
13
+ 'use strict';
14
+
15
+ import { Router } from 'express';
16
+ import { existsSync, readFileSync } from 'node:fs';
17
+ import { join } from 'node:path';
18
+ import { homedir } from 'node:os';
19
+ import { wrap } from './_shared.mjs';
20
+
21
+ /** Default root: projectRoot > cwd > $HOME */
22
+ function resolveRoot(projectRoot) {
23
+ if (projectRoot && projectRoot !== '.') return projectRoot;
24
+ try { return process.cwd(); } catch { return homedir(); }
25
+ }
26
+
27
+ /**
28
+ * @param {object} deps
29
+ * @param {string} [deps.projectRoot]
30
+ * @returns {import('express').Router}
31
+ */
32
+ export function createDecisionsRouter({ projectRoot } = {}) {
33
+ const router = Router();
34
+ const root = projectRoot ?? resolveRoot(projectRoot);
35
+
36
+ // Lazy-import SDK to avoid hard coupling at boot time.
37
+ async function getDecisionsMod() {
38
+ // Try the published SDK first, then fall back to monorepo dist.
39
+ try {
40
+ return await import('@polderlabs/bizar-sdk/learning');
41
+ } catch {
42
+ return await import('../../../packages/sdk/dist/learning/index.js');
43
+ }
44
+ }
45
+
46
+ // GET /decisions — list + tamper status
47
+ router.get('/decisions', wrap(async (_req, res) => {
48
+ let mod;
49
+ try {
50
+ mod = await getDecisionsMod();
51
+ } catch (err) {
52
+ res.status(503).json({ error: 'unavailable', message: 'SDK not loaded', detail: err?.message });
53
+ return;
54
+ }
55
+
56
+ const decisions = mod.listDecisions ? mod.listDecisions({ project: root }) : [];
57
+ const verified = mod.verifyChain ? mod.verifyChain({ project: root }) : { ok: true };
58
+
59
+ // Apply datamark to all string fields to sanitise surrogates.
60
+ const sanitised = decisions.map((entry) => {
61
+ const out = {};
62
+ for (const [k, v] of Object.entries(entry)) {
63
+ out[k] = mod.datamark ? mod.datamark(v) : v;
64
+ }
65
+ return out;
66
+ });
67
+
68
+ res.json({
69
+ decisions: sanitised,
70
+ tamperEvidence: {
71
+ status: verified.ok ? 'intact' : 'broken',
72
+ at: verified.at ?? null,
73
+ },
74
+ });
75
+ }));
76
+
77
+ return router;
78
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * src/server/routes/headroom.mjs
3
+ *
4
+ * v1.0.0 — REST endpoints for Headroom management.
5
+ *
6
+ * Mounted at /api/headroom/* by api.mjs.
7
+ */
8
+ import { Router } from 'express';
9
+ import {
10
+ getHeadroomStatus,
11
+ getHeadroomStats,
12
+ installHeadroom,
13
+ wrapCline,
14
+ unwrapCline,
15
+ startProxy,
16
+ stopProxy,
17
+ getClineConfig,
18
+ headroomStartupHook,
19
+ } from '../headroom.mjs';
20
+ import { wrap } from './_shared.mjs';
21
+
22
+ export function createHeadroomRouter() {
23
+ const router = Router();
24
+
25
+ // GET /api/headroom/status
26
+ router.get('/status', wrap(async (_req, res) => {
27
+ const status = await getHeadroomStatus();
28
+ res.json(status);
29
+ }));
30
+
31
+ // GET /api/headroom/stats?hours=24
32
+ router.get('/stats', wrap(async (req, res) => {
33
+ const hours = Math.max(1, Math.min(parseInt(req.query.hours, 10) || 24, 720));
34
+ const stats = await getHeadroomStats({ hours });
35
+ res.json(stats);
36
+ }));
37
+
38
+ // POST /api/headroom/install
39
+ router.post('/install', wrap(async (req, res) => {
40
+ const { force = false } = req.body || {};
41
+ const result = await installHeadroom({ force: Boolean(force) });
42
+ res.json(result);
43
+ }));
44
+
45
+ // POST /api/headroom/wrap
46
+ router.post('/wrap', wrap(async (req, res) => {
47
+ const { port } = req.body || {};
48
+ const result = await wrapCline({
49
+ port: port ? Math.max(1, Math.min(parseInt(port, 10), 65535)) : 8787,
50
+ });
51
+ res.json(result);
52
+ }));
53
+
54
+ // POST /api/headroom/unwrap
55
+ router.post('/unwrap', wrap(async (_req, res) => {
56
+ const result = await unwrapCline();
57
+ res.json(result);
58
+ }));
59
+
60
+ // POST /api/headroom/proxy/start
61
+ router.post('/proxy/start', wrap(async (req, res) => {
62
+ const { port, host } = req.body || {};
63
+ const result = await startProxy({
64
+ port: port ? Math.max(1, Math.min(parseInt(port, 10), 65535)) : 8787,
65
+ host: typeof host === 'string' && host ? host : '127.0.0.1',
66
+ });
67
+ res.json(result);
68
+ }));
69
+
70
+ // POST /api/headroom/proxy/stop
71
+ router.post('/proxy/stop', wrap(async (_req, res) => {
72
+ const result = await stopProxy();
73
+ res.json(result);
74
+ }));
75
+
76
+ // GET /api/headroom/cline-config
77
+ router.get('/cline-config', wrap(async (_req, res) => {
78
+ const config = await getClineConfig();
79
+ res.json(config);
80
+ }));
81
+
82
+ // POST /api/headroom/auto-route — configure all providers to route through Headroom
83
+ router.post('/auto-route', wrap(async (_req, res) => {
84
+ const { loadConfig, saveConfig } = await import('../providers-store.mjs');
85
+ const cfg = loadConfig();
86
+ const headroomPort = 8787;
87
+ const proxyUrl = `http://127.0.0.1:${headroomPort}/v1`;
88
+
89
+ // For each provider, prepend the headroom proxy URL to baseURL
90
+ const providers = cfg.provider || {};
91
+ let changed = 0;
92
+ for (const [id, p] of Object.entries(providers)) {
93
+ if (!p || typeof p !== 'object') continue;
94
+ const baseURL = p.baseURL || p.options?.baseURL || '';
95
+ // Only update if not already routed
96
+ if (baseURL && !baseURL.includes('127.0.0.1:8787') && !baseURL.includes('localhost:8787')) {
97
+ const newBaseURL = `${proxyUrl}/${baseURL.replace(/^https?:\/\//, '')}`;
98
+ if (p.options) {
99
+ providers[id] = { ...p, options: { ...p.options, baseURL: newBaseURL } };
100
+ } else {
101
+ providers[id] = { ...p, baseURL: newBaseURL };
102
+ }
103
+ changed++;
104
+ }
105
+ }
106
+ cfg.provider = providers;
107
+ saveConfig(cfg);
108
+
109
+ res.json({ ok: true, changed, message: `Updated ${changed} provider(s) to route through Headroom proxy.` });
110
+ }));
111
+
112
+ // POST /api/headroom/startup-hook — trigger the startup hook programmatically
113
+ router.post('/startup-hook', wrap(async (_req, res) => {
114
+ const { readSettings } = await import('./_shared.mjs');
115
+ const settings = readSettings();
116
+ const headroomSettings = settings?.data?.headroom;
117
+ if (!headroomSettings) {
118
+ res.status(400).json({ error: 'bad_request', message: 'Headroom settings not found in settings.json' });
119
+ return;
120
+ }
121
+ const result = await headroomStartupHook(headroomSettings);
122
+ res.json(result);
123
+ }));
124
+
125
+ return router;
126
+ }
@@ -6,6 +6,7 @@
6
6
  * GET /api/model-router — full policy + agent→model map
7
7
  * GET /api/model-router/models — live model list from the local router
8
8
  * GET /api/model-router/agents — agent→model map only
9
+ * GET /api/model-router/resolve/:agent — concrete model + endpoint for an agent
9
10
  *
10
11
  * The local router URL defaults to ANTHROPIC_BASE_URL or
11
12
  * BIZAR_MODEL_ROUTER_URL or `http://localhost:20128/v1`.
@@ -67,6 +68,45 @@ async function fetchLiveModels(endpoint) {
67
68
  }
68
69
  }
69
70
 
71
+ /**
72
+ * v10.1.0 — Resolve the concrete model + endpoint for a named agent
73
+ * directly from the on-disk policy. No SDK import needed (keeps the
74
+ * dashboard route surface lightweight). Used by the front-end's
75
+ * "agent fleet" view, which renders one card per agent with its
76
+ * modelId + endpoint badge.
77
+ */
78
+ function resolveAgentFromPolicy(policy, agent, endpoint) {
79
+ const agents = policy?.agents || {};
80
+ const entry = agents[agent];
81
+ if (entry && typeof entry.model === 'string') {
82
+ return {
83
+ agent,
84
+ modelId: entry.model,
85
+ tier: typeof entry.tier === 'string' ? entry.tier : 'default',
86
+ endpoint,
87
+ rationale: typeof entry.rationale === 'string' ? entry.rationale : '',
88
+ };
89
+ }
90
+ // Fallback: first known entry by name, otherwise the default tier.
91
+ const fallback = Object.values(agents).find((e) => e && typeof e.model === 'string');
92
+ if (fallback) {
93
+ return {
94
+ agent,
95
+ modelId: fallback.model,
96
+ tier: typeof fallback.tier === 'string' ? fallback.tier : 'default',
97
+ endpoint,
98
+ rationale: 'fallback (agent not in policy)',
99
+ };
100
+ }
101
+ return {
102
+ agent,
103
+ modelId: 'bizar/MiniMax-M3',
104
+ tier: 'default',
105
+ endpoint,
106
+ rationale: 'fallback (no policy)',
107
+ };
108
+ }
109
+
70
110
  /**
71
111
  * @param {object} deps
72
112
  * @param {object} deps.state
@@ -99,5 +139,20 @@ export function createModelRouterRouter({ state }) {
99
139
  res.json({ agents: policy.agents || {}, tiers: policy.tiers || {} });
100
140
  }));
101
141
 
142
+ // v10.1.0 — Resolve one agent to its concrete model + endpoint.
143
+ // The front-end's ModelRouter page calls this so it doesn't need to
144
+ // duplicate the registry logic client-side.
145
+ router.get('/model-router/resolve/:agent', wrap(async (req, res) => {
146
+ const agent = String(req.params.agent || '').trim();
147
+ if (!/^[a-z][a-z0-9_-]{0,63}$/i.test(agent)) {
148
+ res.status(400).json({ error: 'bad_slug', message: 'agent must match /^[a-z][a-z0-9_-]{0,63}$/' });
149
+ return;
150
+ }
151
+ const policy = await loadPolicy();
152
+ const endpoint = resolveEndpoint(state);
153
+ const resolved = resolveAgentFromPolicy(policy, agent, endpoint);
154
+ res.json(resolved);
155
+ }));
156
+
102
157
  return router;
103
158
  }
@@ -73,4 +73,32 @@ test('GET /api/model-router/models probe handles unreachable endpoint gracefully
73
73
  if (prev === undefined) delete process.env.BIZAR_MODEL_ROUTER_URL;
74
74
  else process.env.BIZAR_MODEL_ROUTER_URL = prev;
75
75
  }
76
+ });
77
+
78
+ test('GET /api/model-router/resolve/:agent returns the concrete model + endpoint', async () => {
79
+ const app = buildApp();
80
+ const { status, body } = await getJson(app, '/api/model-router/resolve/tyr');
81
+ assert.equal(status, 200);
82
+ assert.equal(body.agent, 'tyr');
83
+ assert.match(body.modelId, /gpt-5\.6-terra/, 'tyr uses high-tier terra');
84
+ assert.match(body.endpoint, /^http/, 'endpoint is a URL');
85
+ assert.equal(typeof body.tier, 'string');
86
+ });
87
+
88
+ test('GET /api/model-router/resolve/:agent falls back for unknown agents', async () => {
89
+ const app = buildApp();
90
+ const { status, body } = await getJson(app, '/api/model-router/resolve/nonexistent-agent-xyz');
91
+ assert.equal(status, 200);
92
+ assert.equal(body.agent, 'nonexistent-agent-xyz');
93
+ assert.match(body.modelId, /[a-z0-9/_.-]+/, 'returns a model id');
94
+ assert.match(body.endpoint, /^http/, 'endpoint is a URL');
95
+ });
96
+
97
+ test('GET /api/model-router/resolve/:agent rejects bad slugs', async () => {
98
+ const app = buildApp();
99
+ // Express decodes percent-encoded path segments before the handler runs.
100
+ // Use a slug that's syntactically illegal per the route's regex.
101
+ const { status, body } = await getJson(app, '/api/model-router/resolve/has spaces');
102
+ assert.equal(status, 400);
103
+ assert.equal(body.error, 'bad_slug');
76
104
  });
@@ -0,0 +1,80 @@
1
+ /**
2
+ * src/server/routes/sessions.mjs
3
+ *
4
+ * Pillar A — Session heartbeat list + stop.
5
+ *
6
+ * GET /api/sessions — list live sessions from .harness/traces/heartbeat.jsonl
7
+ * POST /api/sessions/:id/stop — mark a session as done
8
+ */
9
+
10
+ import { Router } from "express";
11
+ import { existsSync, readFileSync, appendFileSync, mkdirSync } from "node:fs";
12
+ import { join } from "node:path";
13
+ import { wrap } from "./_shared.mjs";
14
+
15
+ const HEARTBEAT_FILE = ".harness/traces/heartbeat.jsonl";
16
+
17
+ function resolveHeartbeatPath(repoRoot) {
18
+ return join(repoRoot ?? process.cwd(), HEARTBEAT_FILE);
19
+ }
20
+
21
+ /**
22
+ * @param {string} repoRoot
23
+ * @returns {Array<{session_id: string, started_at: string, last_heartbeat_at: string, status: string}>}
24
+ */
25
+ function readSessions(repoRoot) {
26
+ const fp = resolveHeartbeatPath(repoRoot);
27
+ if (!existsSync(fp)) return [];
28
+ try {
29
+ const raw = readFileSync(fp, "utf-8");
30
+ const lines = raw.split("\n").filter(Boolean);
31
+ // Deduplicate by session_id, keeping the last record per session
32
+ const map = new Map();
33
+ for (const line of lines) {
34
+ try {
35
+ const rec = JSON.parse(line);
36
+ if (rec?.session_id) map.set(rec.session_id, rec);
37
+ } catch {
38
+ // skip malformed lines
39
+ }
40
+ }
41
+ return Array.from(map.values());
42
+ } catch {
43
+ return [];
44
+ }
45
+ }
46
+
47
+ export function createSessionsRouter({ projectRoot = process.cwd() } = {}) {
48
+ const router = Router();
49
+
50
+ // GET /api/sessions
51
+ router.get("/sessions", wrap(async (_req, res) => {
52
+ const sessions = readSessions(projectRoot);
53
+ res.json({ sessions });
54
+ }));
55
+
56
+ // POST /api/sessions/:id/stop
57
+ router.post("/sessions/:id/stop", wrap(async (req, res) => {
58
+ const id = String(req.params?.id ?? "").trim();
59
+ if (!id) {
60
+ res.status(400).json({ error: "bad_request", message: "session id is required" });
61
+ return;
62
+ }
63
+ const fp = resolveHeartbeatPath(projectRoot);
64
+ // Ensure parent dir exists
65
+ const dir = join(fp, "..");
66
+ if (!existsSync(dir)) {
67
+ mkdirSync(dir, { recursive: true });
68
+ }
69
+ const record = {
70
+ session_id: id,
71
+ started_at: new Date().toISOString(),
72
+ last_heartbeat_at: new Date().toISOString(),
73
+ status: "done",
74
+ };
75
+ appendFileSync(fp, JSON.stringify(record) + "\n", "utf-8");
76
+ res.json({ session_id: id, status: "done" });
77
+ }));
78
+
79
+ return router;
80
+ }