@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
@@ -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
- // v3.20.15 read `artifact.mdx` (the CLI's source-of-truth name from
176
- // cli/artifact.mjs:writePlanFile), with `plan.mdx` as a fallback for
177
- // legacy v0 plans that still exist on disk. Without this fallback,
178
- // every artifact opened in the dashboard showed empty content even
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
- planMdx,
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, '&amp;')
243
+ .replace(/</g, '&lt;')
244
+ .replace(/>/g, '&gt;');
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
- return { slug, dir, meta, canvas, planMdx: '' };
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 (title, status, tags, description). */
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
- return { slug, dir, meta, canvas, planMdx: safeReadText(join(dir, 'plan.mdx')) };
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, '&amp;')
278
+ .replace(/</g, '&lt;')
279
+ .replace(/>/g, '&gt;')
280
+ .replace(/"/g, '&quot;');
281
+ }