@signalflare-ai/ui 0.5.0 → 1.0.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 (316) hide show
  1. package/CHANGELOG.md +117 -1
  2. package/ai/USAGE.md +64 -0
  3. package/ai/component-registry.json +492 -618
  4. package/ai/component-registry.md +167 -85
  5. package/ai/schemas.ts +545 -102
  6. package/bin/sf.js +2 -3
  7. package/dist/.build-complete +1 -1
  8. package/dist/ai/schemas.d.ts +1659 -5532
  9. package/dist/ai/schemas.d.ts.map +1 -1
  10. package/dist/{ai-actions-DG1dhDMP.js → ai-actions-DSVeQn4e.js} +1 -1
  11. package/dist/{ai-actions-DG1dhDMP.js.map → ai-actions-DSVeQn4e.js.map} +1 -1
  12. package/dist/{ai-agent-card-BbtL4NII.js → ai-agent-card-BXHwhWAU.js} +1 -1
  13. package/dist/{ai-agent-card-BbtL4NII.js.map → ai-agent-card-BXHwhWAU.js.map} +1 -1
  14. package/dist/{ai-approval-Mb7-BY6i.js → ai-approval-aa0qvjFN.js} +1 -1
  15. package/dist/{ai-approval-Mb7-BY6i.js.map → ai-approval-aa0qvjFN.js.map} +1 -1
  16. package/dist/{ai-code-block-BI_z0UVR.js → ai-code-block-BgtIxtZZ.js} +1 -1
  17. package/dist/{ai-code-block-BI_z0UVR.js.map → ai-code-block-BgtIxtZZ.js.map} +1 -1
  18. package/dist/{ai-conversation-DYtExcrw.js → ai-conversation-CArP7C8K.js} +1 -1
  19. package/dist/{ai-conversation-DYtExcrw.js.map → ai-conversation-CArP7C8K.js.map} +1 -1
  20. package/dist/{ai-info-banner-BpzauUAY.js → ai-info-banner-uFxHHwBA.js} +1 -1
  21. package/dist/{ai-info-banner-BpzauUAY.js.map → ai-info-banner-uFxHHwBA.js.map} +1 -1
  22. package/dist/{ai-message-CV8SBoHM.js → ai-message-BjnFznXy.js} +1 -1
  23. package/dist/{ai-message-CV8SBoHM.js.map → ai-message-BjnFznXy.js.map} +1 -1
  24. package/dist/{ai-mission-header-ByYkJ6YP.js → ai-mission-header-08__gULL.js} +1 -1
  25. package/dist/{ai-mission-header-ByYkJ6YP.js.map → ai-mission-header-08__gULL.js.map} +1 -1
  26. package/dist/ai-part-group-DBtgTgAn.js +277 -0
  27. package/dist/ai-part-group-DBtgTgAn.js.map +1 -0
  28. package/dist/ai-prompt-input-Dy1LfxPk.js +1541 -0
  29. package/dist/ai-prompt-input-Dy1LfxPk.js.map +1 -0
  30. package/dist/{ai-question-Dp1g9k2o.js → ai-question-CHHoDJMg.js} +1 -1
  31. package/dist/{ai-question-Dp1g9k2o.js.map → ai-question-CHHoDJMg.js.map} +1 -1
  32. package/dist/{ai-reasoning-UAmNx_LD.js → ai-reasoning-CnL6ZSr5.js} +84 -5
  33. package/dist/ai-reasoning-CnL6ZSr5.js.map +1 -0
  34. package/dist/{ai-response-BWoVsNQG.js → ai-response-BEUg3xvd.js} +13 -16
  35. package/dist/ai-response-BEUg3xvd.js.map +1 -0
  36. package/dist/{ai-shimmer-BpOmfonu.js → ai-shimmer-By5_L05p.js} +1 -1
  37. package/dist/{ai-shimmer-BpOmfonu.js.map → ai-shimmer-By5_L05p.js.map} +1 -1
  38. package/dist/{ai-status-badge-WhbKVeqn.js → ai-status-badge-BGYGWYF6.js} +1 -1
  39. package/dist/{ai-status-badge-WhbKVeqn.js.map → ai-status-badge-BGYGWYF6.js.map} +1 -1
  40. package/dist/{ai-streaming-text-ClL7FwvD.js → ai-streaming-text-CMfoThV0.js} +1 -1
  41. package/dist/{ai-streaming-text-ClL7FwvD.js.map → ai-streaming-text-CMfoThV0.js.map} +1 -1
  42. package/dist/{ai-subagent-BruGN1UE.js → ai-subagent-DcPRqkAA.js} +1 -1
  43. package/dist/{ai-subagent-BruGN1UE.js.map → ai-subagent-DcPRqkAA.js.map} +1 -1
  44. package/dist/{ai-suggestion-CNsCZj5P.js → ai-suggestion-MgeCg5Ar.js} +1 -1
  45. package/dist/{ai-suggestion-CNsCZj5P.js.map → ai-suggestion-MgeCg5Ar.js.map} +1 -1
  46. package/dist/{ai-task-list-B9CpMDYN.js → ai-task-list-Da9zIm00.js} +9 -12
  47. package/dist/ai-task-list-Da9zIm00.js.map +1 -0
  48. package/dist/{ai-timeline-Bb5ntsr3.js → ai-timeline-Cwu045IR.js} +1 -1
  49. package/dist/ai-timeline-Cwu045IR.js.map +1 -0
  50. package/dist/{ai-tool-BGH8nQ_D.js → ai-tool-Cn1O4xjP.js} +168 -11
  51. package/dist/ai-tool-Cn1O4xjP.js.map +1 -0
  52. package/dist/{ai-usage-bar-BI-p-JBk.js → ai-usage-bar-DjS12DMp.js} +1 -1
  53. package/dist/{ai-usage-bar-BI-p-JBk.js.map → ai-usage-bar-DjS12DMp.js.map} +1 -1
  54. package/dist/catalog.js +3 -3
  55. package/dist/catalog.js.map +1 -1
  56. package/dist/{chart-Bes4MN3C.js → chart-BK3sVPnD.js} +442 -248
  57. package/dist/chart-BK3sVPnD.js.map +1 -0
  58. package/dist/{checkbox-CPX7lBaU.js → checkbox-DYhUmZNw.js} +4 -4
  59. package/dist/checkbox-DYhUmZNw.js.map +1 -0
  60. package/dist/{clipboard-text-92YeCybc.js → clipboard-text-ssybngLw.js} +2 -2
  61. package/dist/{clipboard-text-92YeCybc.js.map → clipboard-text-ssybngLw.js.map} +1 -1
  62. package/dist/{code-DE1Yy1Cu.js → code-Cx-QSoOT.js} +2 -2
  63. package/dist/{code-DE1Yy1Cu.js.map → code-Cx-QSoOT.js.map} +1 -1
  64. package/dist/{combobox-B0bLdsX8.js → combobox-C0iW6a0r.js} +2 -2
  65. package/dist/{combobox-B0bLdsX8.js.map → combobox-C0iW6a0r.js.map} +1 -1
  66. package/dist/command-line/cli.js +22 -27
  67. package/dist/{command-palette-CBTY8EiF.js → command-palette-DGzioeki.js} +2 -2
  68. package/dist/command-palette-DGzioeki.js.map +1 -0
  69. package/dist/components/ai-actions.js +1 -1
  70. package/dist/components/ai-agent-card.js +1 -1
  71. package/dist/components/ai-approval.js +1 -1
  72. package/dist/components/ai-code-block.js +1 -1
  73. package/dist/components/ai-conversation.js +1 -1
  74. package/dist/components/ai-info-banner.js +1 -1
  75. package/dist/components/ai-message.js +1 -1
  76. package/dist/components/ai-mission-header.js +1 -1
  77. package/dist/components/ai-part-group.js +3 -0
  78. package/dist/components/ai-prompt-input.js +2 -2
  79. package/dist/components/ai-question.js +1 -1
  80. package/dist/components/ai-reasoning.js +1 -1
  81. package/dist/components/ai-response.js +1 -1
  82. package/dist/components/ai-shimmer.js +1 -1
  83. package/dist/components/ai-status-badge.js +1 -1
  84. package/dist/components/ai-streaming-text.js +1 -1
  85. package/dist/components/ai-subagent.js +1 -1
  86. package/dist/components/ai-suggestion.js +1 -1
  87. package/dist/components/ai-task-list.js +1 -1
  88. package/dist/components/ai-timeline.js +1 -1
  89. package/dist/components/ai-tool.js +1 -1
  90. package/dist/components/ai-usage-bar.js +1 -1
  91. package/dist/components/chart.js +3 -2
  92. package/dist/components/checkbox.js +1 -1
  93. package/dist/components/clipboard-text.js +1 -1
  94. package/dist/components/code.js +1 -1
  95. package/dist/components/combobox.js +1 -1
  96. package/dist/components/command-palette.js +1 -1
  97. package/dist/components/data-grid.js +1 -1
  98. package/dist/components/date-picker.js +1 -1
  99. package/dist/components/dropdown.js +1 -1
  100. package/dist/components/filters.js +1 -1
  101. package/dist/components/input.js +2 -2
  102. package/dist/components/link.js +2 -2
  103. package/dist/components/link.js.map +1 -1
  104. package/dist/components/pagination.js +1 -1
  105. package/dist/components/radio.js +1 -1
  106. package/dist/components/select.js +1 -1
  107. package/dist/components/sensitive-input.js +1 -1
  108. package/dist/components/sidebar.js +1 -1
  109. package/dist/components/sparkline.js +3 -0
  110. package/dist/components/stat-card.js +3 -0
  111. package/dist/components/table.js +1 -1
  112. package/dist/components/text-roll.js +3 -0
  113. package/dist/components/theme-toggle.js +1 -1
  114. package/dist/components/use-agent-harness.js +1 -1
  115. package/dist/{data-grid-UJ9ja5cu.js → data-grid-CG76N_hK.js} +6 -6
  116. package/dist/data-grid-CG76N_hK.js.map +1 -0
  117. package/dist/{date-picker-ebekkC3R.js → date-picker-Dqg9L4xu.js} +2 -2
  118. package/dist/{date-picker-ebekkC3R.js.map → date-picker-Dqg9L4xu.js.map} +1 -1
  119. package/dist/{dist-BNlyONdD.js → dist-1-gcEL2L.js} +224 -135
  120. package/dist/dist-1-gcEL2L.js.map +1 -0
  121. package/dist/{dropdown-J5T4pHaR.js → dropdown-qnEYRFXZ.js} +2 -2
  122. package/dist/{dropdown-J5T4pHaR.js.map → dropdown-qnEYRFXZ.js.map} +1 -1
  123. package/dist/echart-DURZEyai.js +314 -0
  124. package/dist/echart-DURZEyai.js.map +1 -0
  125. package/dist/{filters-BdBogf7D.js → filters-Bw_U6ZTx.js} +5 -5
  126. package/dist/filters-Bw_U6ZTx.js.map +1 -0
  127. package/dist/flow-BRsYUCJa.js.map +1 -1
  128. package/dist/genui.js +2 -2
  129. package/dist/genui.js.map +1 -1
  130. package/dist/index.js +45 -42
  131. package/dist/index.js.map +1 -1
  132. package/dist/{input-BxQAnXki.js → input-DXYUjGgD.js} +2 -2
  133. package/dist/{input-BxQAnXki.js.map → input-DXYUjGgD.js.map} +1 -1
  134. package/dist/{input-Cn25I4o5.js → input-DddtBN-g.js} +2 -2
  135. package/dist/{input-Cn25I4o5.js.map → input-DddtBN-g.js.map} +1 -1
  136. package/dist/layer-card-BME0eljh.js.map +1 -1
  137. package/dist/{pagination-C_YqCy8l.js → pagination-BVqdlONY.js} +2 -2
  138. package/dist/{pagination-C_YqCy8l.js.map → pagination-BVqdlONY.js.map} +1 -1
  139. package/dist/primitives/otp-field.js +2 -0
  140. package/dist/primitives.js +1 -0
  141. package/dist/{radio-B7zg1wUI.js → radio-BNSwOt3B.js} +3 -3
  142. package/dist/radio-BNSwOt3B.js.map +1 -0
  143. package/dist/{select-9p721G00.js → select-1w2aebGQ.js} +2 -2
  144. package/dist/select-1w2aebGQ.js.map +1 -0
  145. package/dist/{sensitive-input-D5je2NLl.js → sensitive-input-82Cez3vj.js} +2 -2
  146. package/dist/{sensitive-input-D5je2NLl.js.map → sensitive-input-82Cez3vj.js.map} +1 -1
  147. package/dist/{sidebar-DOwBrq57.js → sidebar-CAsCmSpM.js} +3 -3
  148. package/dist/sidebar-CAsCmSpM.js.map +1 -0
  149. package/dist/sparkline-DdbeM4Ai.js +108 -0
  150. package/dist/sparkline-DdbeM4Ai.js.map +1 -0
  151. package/dist/src/blocks/agent-harness/agent-harness.d.ts +30 -9
  152. package/dist/src/blocks/agent-harness/agent-harness.d.ts.map +1 -1
  153. package/dist/src/blocks/agent-harness/agent-harness.stories.tsx +114 -0
  154. package/dist/src/blocks/agent-harness/agent-harness.tsx +144 -63
  155. package/dist/src/blocks/commander/commander.stories.tsx +31 -0
  156. package/dist/src/blocks/dashboard-grid/dashboard-grid.d.ts +48 -0
  157. package/dist/src/blocks/dashboard-grid/dashboard-grid.d.ts.map +1 -0
  158. package/dist/src/blocks/dashboard-grid/dashboard-grid.stories.tsx +19 -0
  159. package/dist/src/blocks/dashboard-grid/dashboard-grid.tsx +110 -0
  160. package/dist/src/blocks/dashboard-grid/index.d.ts +2 -0
  161. package/dist/src/blocks/dashboard-grid/index.d.ts.map +1 -0
  162. package/dist/src/blocks/delete-resource/delete-resource.stories.tsx +31 -0
  163. package/dist/src/blocks/map-block/map-block.stories.tsx +41 -0
  164. package/dist/src/blocks/metrics-overview/index.d.ts +2 -0
  165. package/dist/src/blocks/metrics-overview/index.d.ts.map +1 -0
  166. package/dist/src/blocks/metrics-overview/metrics-overview.d.ts +67 -0
  167. package/dist/src/blocks/metrics-overview/metrics-overview.d.ts.map +1 -0
  168. package/dist/src/blocks/metrics-overview/metrics-overview.stories.tsx +26 -0
  169. package/dist/src/blocks/metrics-overview/metrics-overview.tsx +139 -0
  170. package/dist/src/blocks/page-header/page-header.stories.tsx +56 -0
  171. package/dist/src/blocks/resource-list/resource-list.stories.tsx +31 -0
  172. package/dist/src/catalog/catalog.d.ts +1 -1
  173. package/dist/src/catalog/index.d.ts +1 -1
  174. package/dist/src/catalog/types.d.ts +1 -1
  175. package/dist/src/command-line/build-cli.d.ts +1 -1
  176. package/dist/src/command-line/cli.d.ts +1 -1
  177. package/dist/src/command-line/commands/add.d.ts +1 -1
  178. package/dist/src/command-line/commands/add.d.ts.map +1 -1
  179. package/dist/src/command-line/commands/ai.d.ts.map +1 -1
  180. package/dist/src/command-line/commands/blocks.d.ts +1 -1
  181. package/dist/src/command-line/commands/blocks.d.ts.map +1 -1
  182. package/dist/src/command-line/commands/doc.d.ts +1 -1
  183. package/dist/src/command-line/commands/doc.d.ts.map +1 -1
  184. package/dist/src/command-line/commands/ls.d.ts +1 -1
  185. package/dist/src/command-line/commands/ls.d.ts.map +1 -1
  186. package/dist/src/command-line/commands/migrate.d.ts +3 -3
  187. package/dist/src/command-line/commands/migrate.d.ts.map +1 -1
  188. package/dist/src/command-line/utils/config.d.ts +1 -1
  189. package/dist/src/command-line/utils/transformer.d.ts +1 -1
  190. package/dist/src/components/ai-part-group/ai-part-group.d.ts +134 -0
  191. package/dist/src/components/ai-part-group/ai-part-group.d.ts.map +1 -0
  192. package/dist/src/components/ai-part-group/index.d.ts +2 -0
  193. package/dist/src/components/ai-part-group/index.d.ts.map +1 -0
  194. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts +196 -7
  195. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
  196. package/dist/src/components/ai-prompt-input/controller.d.ts +41 -0
  197. package/dist/src/components/ai-prompt-input/controller.d.ts.map +1 -0
  198. package/dist/src/components/ai-prompt-input/index.d.ts +3 -1
  199. package/dist/src/components/ai-prompt-input/index.d.ts.map +1 -1
  200. package/dist/src/components/ai-prompt-input/types.d.ts +86 -0
  201. package/dist/src/components/ai-prompt-input/types.d.ts.map +1 -0
  202. package/dist/src/components/ai-reasoning/ai-reasoning.d.ts +17 -1
  203. package/dist/src/components/ai-reasoning/ai-reasoning.d.ts.map +1 -1
  204. package/dist/src/components/ai-response/ai-response.d.ts +1 -2
  205. package/dist/src/components/ai-response/ai-response.d.ts.map +1 -1
  206. package/dist/src/components/ai-task-list/ai-task-list.d.ts.map +1 -1
  207. package/dist/src/components/ai-tool/ai-tool.d.ts +17 -1
  208. package/dist/src/components/ai-tool/ai-tool.d.ts.map +1 -1
  209. package/dist/src/components/chart/area-chart.d.ts +69 -0
  210. package/dist/src/components/chart/area-chart.d.ts.map +1 -0
  211. package/dist/src/components/chart/bar-chart.d.ts +60 -0
  212. package/dist/src/components/chart/bar-chart.d.ts.map +1 -0
  213. package/dist/src/components/chart/color.d.ts +56 -0
  214. package/dist/src/components/chart/color.d.ts.map +1 -1
  215. package/dist/src/components/chart/echart.d.ts.map +1 -1
  216. package/dist/src/components/chart/index.d.ts +5 -0
  217. package/dist/src/components/chart/index.d.ts.map +1 -1
  218. package/dist/src/components/chart/pie-chart.d.ts +64 -0
  219. package/dist/src/components/chart/pie-chart.d.ts.map +1 -0
  220. package/dist/src/components/chart/scatter-chart.d.ts +57 -0
  221. package/dist/src/components/chart/scatter-chart.d.ts.map +1 -0
  222. package/dist/src/components/chart/stacked-bar-chart.d.ts +59 -0
  223. package/dist/src/components/chart/stacked-bar-chart.d.ts.map +1 -0
  224. package/dist/src/components/chart/timeseries-chart.d.ts.map +1 -1
  225. package/dist/src/components/code/code.d.ts +1 -1
  226. package/dist/src/components/command-palette/command-palette.d.ts +1 -1
  227. package/dist/src/components/data-grid/data-grid.d.ts.map +1 -1
  228. package/dist/src/components/data-grid/index.d.ts +1 -1
  229. package/dist/src/components/data-grid/index.d.ts.map +1 -1
  230. package/dist/src/components/data-grid/types.d.ts.map +1 -1
  231. package/dist/src/components/date-picker/date-picker.d.ts +2 -2
  232. package/dist/src/components/filters/filters.d.ts.map +1 -1
  233. package/dist/src/components/filters/helpers.d.ts.map +1 -1
  234. package/dist/src/components/filters/types.d.ts.map +1 -1
  235. package/dist/src/components/layer-card/layer-card.d.ts +1 -1
  236. package/dist/src/components/link/link.d.ts +2 -2
  237. package/dist/src/components/radio/radio.d.ts +1 -1
  238. package/dist/src/components/select/select.d.ts +1 -1
  239. package/dist/src/components/sidebar/sidebar.d.ts +2 -2
  240. package/dist/src/components/sparkline/index.d.ts +2 -0
  241. package/dist/src/components/sparkline/index.d.ts.map +1 -0
  242. package/dist/src/components/sparkline/sparkline.d.ts +52 -0
  243. package/dist/src/components/sparkline/sparkline.d.ts.map +1 -0
  244. package/dist/src/components/stat-card/index.d.ts +2 -0
  245. package/dist/src/components/{ai-loader → stat-card}/index.d.ts.map +1 -1
  246. package/dist/src/components/stat-card/stat-card.d.ts +80 -0
  247. package/dist/src/components/stat-card/stat-card.d.ts.map +1 -0
  248. package/dist/src/components/text-roll/index.d.ts +2 -0
  249. package/dist/src/components/text-roll/index.d.ts.map +1 -0
  250. package/dist/src/components/text-roll/text-roll.d.ts +49 -0
  251. package/dist/src/components/text-roll/text-roll.d.ts.map +1 -0
  252. package/dist/src/components/toast/toast.d.ts.map +1 -1
  253. package/dist/src/components/use-agent-harness/use-agent-harness.d.ts +2 -2
  254. package/dist/src/genui/genui.d.ts.map +1 -1
  255. package/dist/src/index.d.ts +5 -2
  256. package/dist/src/index.d.ts.map +1 -1
  257. package/dist/src/primitives/index.d.ts +1 -0
  258. package/dist/src/primitives/index.d.ts.map +1 -1
  259. package/dist/src/primitives/otp-field.d.ts +13 -0
  260. package/dist/src/primitives/otp-field.d.ts.map +1 -0
  261. package/dist/src/registry/index.d.ts +1 -1
  262. package/dist/src/registry/types.d.ts +1 -1
  263. package/dist/stat-card-CEZscNh8.js +103 -0
  264. package/dist/stat-card-CEZscNh8.js.map +1 -0
  265. package/dist/styles/sf-binding.css +20 -62
  266. package/dist/styles/sf-standalone.css +2 -2
  267. package/dist/styles/shadcn.css +120 -0
  268. package/dist/styles/theme-blue-tint.css +98 -0
  269. package/dist/styles/theme-fedramp.css +3 -12
  270. package/dist/styles/theme-minimal.css +26 -104
  271. package/dist/styles/theme-sf.css +96 -114
  272. package/dist/{table-CIMx0Oq0.js → table-Rv4JMy0B.js} +2 -2
  273. package/dist/{table-CIMx0Oq0.js.map → table-Rv4JMy0B.js.map} +1 -1
  274. package/dist/text-roll-BZ3I1umc.js +79 -0
  275. package/dist/text-roll-BZ3I1umc.js.map +1 -0
  276. package/dist/{theme-toggle-Dpgnoj_Q.js → theme-toggle-Bhu681D7.js} +1 -1
  277. package/dist/{theme-toggle-Dpgnoj_Q.js.map → theme-toggle-Bhu681D7.js.map} +1 -1
  278. package/dist/{use-agent-harness-DZzcn96L.js → use-agent-harness-BMyF8pTq.js} +5 -5
  279. package/dist/use-agent-harness-BMyF8pTq.js.map +1 -0
  280. package/package.json +48 -19
  281. package/scripts/component-registry/discovery.ts +2 -2
  282. package/scripts/component-registry/index.ts +1 -1
  283. package/scripts/component-registry/props-filter.ts +1 -1
  284. package/scripts/component-registry/utils.ts +5 -5
  285. package/scripts/component-registry/variant-parser.ts +124 -19
  286. package/scripts/convert-demos-to-stories.ts +253 -0
  287. package/scripts/css-build.ts +4 -3
  288. package/scripts/generate-primitives.ts +11 -3
  289. package/scripts/theme-generator/config.ts +339 -71
  290. package/scripts/theme-generator/generate-css.ts +17 -3
  291. package/scripts/theme-generator/index.ts +3 -3
  292. package/scripts/theme-generator/migrate.ts +1 -1
  293. package/dist/ai-loader-Cr3eQkNS.js +0 -134
  294. package/dist/ai-loader-Cr3eQkNS.js.map +0 -1
  295. package/dist/ai-prompt-input-Bo1YuJly.js +0 -769
  296. package/dist/ai-prompt-input-Bo1YuJly.js.map +0 -1
  297. package/dist/ai-reasoning-UAmNx_LD.js.map +0 -1
  298. package/dist/ai-response-BWoVsNQG.js.map +0 -1
  299. package/dist/ai-task-list-B9CpMDYN.js.map +0 -1
  300. package/dist/ai-timeline-Bb5ntsr3.js.map +0 -1
  301. package/dist/ai-tool-BGH8nQ_D.js.map +0 -1
  302. package/dist/chart-Bes4MN3C.js.map +0 -1
  303. package/dist/checkbox-CPX7lBaU.js.map +0 -1
  304. package/dist/command-palette-CBTY8EiF.js.map +0 -1
  305. package/dist/components/ai-loader.js +0 -3
  306. package/dist/data-grid-UJ9ja5cu.js.map +0 -1
  307. package/dist/dist-BNlyONdD.js.map +0 -1
  308. package/dist/filters-BdBogf7D.js.map +0 -1
  309. package/dist/radio-B7zg1wUI.js.map +0 -1
  310. package/dist/select-9p721G00.js.map +0 -1
  311. package/dist/sidebar-DOwBrq57.js.map +0 -1
  312. package/dist/src/components/ai-loader/ai-loader.d.ts +0 -44
  313. package/dist/src/components/ai-loader/ai-loader.d.ts.map +0 -1
  314. package/dist/src/components/ai-loader/index.d.ts +0 -2
  315. package/dist/styles/theme-navigator.css +0 -137
  316. package/dist/use-agent-harness-DZzcn96L.js.map +0 -1
@@ -0,0 +1,79 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { motion } from "motion/react";
4
+ //#region src/components/text-roll/text-roll.tsx
5
+ var DEFAULT_VARIANTS = {
6
+ enter: {
7
+ initial: { rotateX: 0 },
8
+ animate: { rotateX: 90 }
9
+ },
10
+ exit: {
11
+ initial: { rotateX: 90 },
12
+ animate: { rotateX: 0 }
13
+ }
14
+ };
15
+ /**
16
+ * Letter-by-letter roll animation. Each character flips on the X axis: the
17
+ * current letter rolls up and out, the new letter rolls in from below.
18
+ * Good for title changes (e.g. a streaming activity group swapping its
19
+ * current-step label) where the text content is short and the change should
20
+ * register visually.
21
+ *
22
+ * Wraps the string in an `aria-hidden` visual stack with a screen-reader-only
23
+ * copy of the full text so a11y tools always read the real content.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * <TextRoll key={title}>{title}</TextRoll>
28
+ * ```
29
+ */
30
+ function TextRoll({ children, duration = .5, getEnterDelay = (i) => i * .1, getExitDelay = (i) => i * .1 + .2, className, transition = { ease: "easeIn" }, variants, onAnimationComplete }) {
31
+ const letters = children.split("");
32
+ return /* @__PURE__ */ jsxs("span", {
33
+ className,
34
+ children: [letters.map((letter, i) => {
35
+ const display = letter === " " ? "\xA0" : letter;
36
+ return /* @__PURE__ */ jsxs("span", {
37
+ "aria-hidden": "true",
38
+ className: "relative inline-block [perspective:10000px] [transform-style:preserve-3d] [width:auto]",
39
+ children: [
40
+ /* @__PURE__ */ jsx(motion.span, {
41
+ animate: variants?.enter?.animate ?? DEFAULT_VARIANTS.enter.animate,
42
+ className: "absolute inline-block [backface-visibility:hidden] [transform-origin:50%_25%]",
43
+ initial: variants?.enter?.initial ?? DEFAULT_VARIANTS.enter.initial,
44
+ transition: {
45
+ ...transition,
46
+ duration,
47
+ delay: getEnterDelay(i)
48
+ },
49
+ children: display
50
+ }),
51
+ /* @__PURE__ */ jsx(motion.span, {
52
+ animate: variants?.exit?.animate ?? DEFAULT_VARIANTS.exit.animate,
53
+ className: "absolute inline-block [backface-visibility:hidden] [transform-origin:50%_100%]",
54
+ initial: variants?.exit?.initial ?? DEFAULT_VARIANTS.exit.initial,
55
+ onAnimationComplete: letters.length === i + 1 ? onAnimationComplete : void 0,
56
+ transition: {
57
+ ...transition,
58
+ duration,
59
+ delay: getExitDelay(i)
60
+ },
61
+ children: display
62
+ }),
63
+ /* @__PURE__ */ jsx("span", {
64
+ className: "invisible",
65
+ children: display
66
+ })
67
+ ]
68
+ }, i);
69
+ }), /* @__PURE__ */ jsx("span", {
70
+ className: "sr-only",
71
+ children
72
+ })]
73
+ });
74
+ }
75
+ TextRoll.displayName = "TextRoll";
76
+ //#endregion
77
+ export { TextRoll as t };
78
+
79
+ //# sourceMappingURL=text-roll-BZ3I1umc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-roll-BZ3I1umc.js","names":[],"sources":["../src/components/text-roll/text-roll.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n motion,\n type Target,\n type TargetAndTransition,\n type Transition,\n type VariantLabels,\n} from \"motion/react\";\n\nexport type TextRollVariants = {\n enter: {\n initial: Target | VariantLabels | boolean;\n animate: TargetAndTransition | VariantLabels;\n };\n exit: {\n initial: Target | VariantLabels | boolean;\n animate: TargetAndTransition | VariantLabels;\n };\n};\n\nexport type TextRollProps = {\n /** Text to animate. Each character rolls in / out independently. */\n children: string;\n /** Duration (seconds) of each letter's enter and exit tween. */\n duration?: number;\n /** Per-letter delay for the enter animation. */\n getEnterDelay?: (index: number) => number;\n /** Per-letter delay for the exit animation. */\n getExitDelay?: (index: number) => number;\n /** Additional CSS classes merged via `cn()`. Use sf semantic tokens only. */\n className?: string;\n /** Shared transition for both enter and exit tweens. */\n transition?: Transition;\n /** Override the default rotate-X roll with custom enter/exit variants. */\n variants?: TextRollVariants;\n /** Fires once the last letter's exit animation finishes. */\n onAnimationComplete?: () => void;\n};\n\nconst DEFAULT_VARIANTS: TextRollVariants = {\n enter: {\n initial: { rotateX: 0 },\n animate: { rotateX: 90 },\n },\n exit: {\n initial: { rotateX: 90 },\n animate: { rotateX: 0 },\n },\n};\n\n/**\n * Letter-by-letter roll animation. Each character flips on the X axis: the\n * current letter rolls up and out, the new letter rolls in from below.\n * Good for title changes (e.g. a streaming activity group swapping its\n * current-step label) where the text content is short and the change should\n * register visually.\n *\n * Wraps the string in an `aria-hidden` visual stack with a screen-reader-only\n * copy of the full text so a11y tools always read the real content.\n *\n * @example\n * ```tsx\n * <TextRoll key={title}>{title}</TextRoll>\n * ```\n */\nexport function TextRoll({\n children,\n duration = 0.5,\n getEnterDelay = (i) => i * 0.1,\n getExitDelay = (i) => i * 0.1 + 0.2,\n className,\n transition = { ease: \"easeIn\" },\n variants,\n onAnimationComplete,\n}: TextRollProps) {\n const letters = children.split(\"\");\n\n return (\n <span className={className}>\n {letters.map((letter, i) => {\n const display = letter === \" \" ? \"\\u00A0\" : letter;\n return (\n <span\n aria-hidden=\"true\"\n className=\"relative inline-block [perspective:10000px] [transform-style:preserve-3d] [width:auto]\"\n // Using index is intentional — letters are positional.\n // biome-ignore lint/suspicious/noArrayIndexKey: positional char animation\n key={i}\n >\n <motion.span\n animate={\n variants?.enter?.animate ?? DEFAULT_VARIANTS.enter.animate\n }\n className=\"absolute inline-block [backface-visibility:hidden] [transform-origin:50%_25%]\"\n initial={\n variants?.enter?.initial ?? DEFAULT_VARIANTS.enter.initial\n }\n transition={{\n ...transition,\n duration,\n delay: getEnterDelay(i),\n }}\n >\n {display}\n </motion.span>\n <motion.span\n animate={variants?.exit?.animate ?? DEFAULT_VARIANTS.exit.animate}\n className=\"absolute inline-block [backface-visibility:hidden] [transform-origin:50%_100%]\"\n initial={variants?.exit?.initial ?? DEFAULT_VARIANTS.exit.initial}\n onAnimationComplete={\n letters.length === i + 1 ? onAnimationComplete : undefined\n }\n transition={{\n ...transition,\n duration,\n delay: getExitDelay(i),\n }}\n >\n {display}\n </motion.span>\n <span className=\"invisible\">{display}</span>\n </span>\n );\n })}\n <span className=\"sr-only\">{children}</span>\n </span>\n );\n}\n\nTextRoll.displayName = \"TextRoll\";\n"],"mappings":";;;;AAwCA,IAAM,mBAAqC;CACzC,OAAO;EACL,SAAS,EAAE,SAAS,GAAG;EACvB,SAAS,EAAE,SAAS,IAAI;EACzB;CACD,MAAM;EACJ,SAAS,EAAE,SAAS,IAAI;EACxB,SAAS,EAAE,SAAS,GAAG;EACxB;CACF;;;;;;;;;;;;;;;;AAiBD,SAAgB,SAAS,EACvB,UACA,WAAW,IACX,iBAAiB,MAAM,IAAI,IAC3B,gBAAgB,MAAM,IAAI,KAAM,IAChC,WACA,aAAa,EAAE,MAAM,UAAU,EAC/B,UACA,uBACgB;CAChB,MAAM,UAAU,SAAS,MAAM,GAAG;AAElC,QACE,qBAAC,QAAD;EAAiB;YAAjB,CACG,QAAQ,KAAK,QAAQ,MAAM;GAC1B,MAAM,UAAU,WAAW,MAAM,SAAW;AAC5C,UACE,qBAAC,QAAD;IACE,eAAY;IACZ,WAAU;cAFZ;KAOE,oBAAC,OAAO,MAAR;MACE,SACE,UAAU,OAAO,WAAW,iBAAiB,MAAM;MAErD,WAAU;MACV,SACE,UAAU,OAAO,WAAW,iBAAiB,MAAM;MAErD,YAAY;OACV,GAAG;OACH;OACA,OAAO,cAAc,EAAE;OACxB;gBAEA;MACW,CAAA;KACd,oBAAC,OAAO,MAAR;MACE,SAAS,UAAU,MAAM,WAAW,iBAAiB,KAAK;MAC1D,WAAU;MACV,SAAS,UAAU,MAAM,WAAW,iBAAiB,KAAK;MAC1D,qBACE,QAAQ,WAAW,IAAI,IAAI,sBAAsB,KAAA;MAEnD,YAAY;OACV,GAAG;OACH;OACA,OAAO,aAAa,EAAE;OACvB;gBAEA;MACW,CAAA;KACd,oBAAC,QAAD;MAAM,WAAU;gBAAa;MAAe,CAAA;KACvC;MAlCA,EAkCA;IAET,EACF,oBAAC,QAAD;GAAM,WAAU;GAAW;GAAgB,CAAA,CACtC;;;AAIX,SAAS,cAAc"}
@@ -126,4 +126,4 @@ function ThemeToggle({ className, mode: controlledMode, onModeChange, cycle = [
126
126
  //#endregion
127
127
  export { getStoredThemeMode as i, SF_THEME_TOGGLE_VARIANTS as n, ThemeToggle as r, SF_THEME_TOGGLE_DEFAULT_VARIANTS as t };
128
128
 
129
- //# sourceMappingURL=theme-toggle-Dpgnoj_Q.js.map
129
+ //# sourceMappingURL=theme-toggle-Bhu681D7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"theme-toggle-Dpgnoj_Q.js","names":[],"sources":["../src/components/theme-toggle/theme-toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { MoonIcon, SunIcon } from \"@phosphor-icons/react\";\nimport { useEffect, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\nimport { Tooltip } from \"../tooltip\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type SFThemeMode = \"light\" | \"dark\" | \"system\";\n\nexport const SF_THEME_TOGGLE_VARIANTS = {\n mode: {\n light: { classes: \"\", description: \"Light mode\" },\n dark: { classes: \"\", description: \"Dark mode\" },\n system: { classes: \"\", description: \"Follow system preference\" },\n },\n} as const;\n\nexport const SF_THEME_TOGGLE_DEFAULT_VARIANTS = {\n mode: \"system\",\n} as const;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nconst STORAGE_KEY = \"theme\";\n\nfunction getSystemTheme(): \"light\" | \"dark\" {\n if (typeof window === \"undefined\") return \"light\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\";\n}\n\nfunction resolveMode(mode: SFThemeMode): \"light\" | \"dark\" {\n return mode === \"system\" ? getSystemTheme() : mode;\n}\n\nfunction applyTheme(mode: SFThemeMode) {\n const resolved = resolveMode(mode);\n document.documentElement.dataset.mode = resolved;\n if (mode === \"system\") {\n localStorage.removeItem(STORAGE_KEY);\n } else {\n localStorage.setItem(STORAGE_KEY, mode);\n }\n}\n\n/**\n * Read the current persisted mode preference from localStorage.\n * Returns \"system\" if nothing is stored.\n */\nexport function getStoredThemeMode(): SFThemeMode {\n if (typeof window === \"undefined\") return \"system\";\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored === \"light\" || stored === \"dark\") return stored;\n return \"system\";\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport interface ThemeToggleProps {\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /**\n * Controlled mode. When provided the component acts as a controlled input —\n * pair with `onModeChange`.\n */\n mode?: SFThemeMode;\n /**\n * Called when the user cycles to a new mode.\n * Receives the new mode value.\n */\n onModeChange?: (mode: SFThemeMode) => void;\n /**\n * Cycle order for clicking. Defaults to `[\"light\", \"dark\", \"system\"]`.\n * Remove `\"system\"` to limit to a simple light/dark toggle.\n */\n cycle?: SFThemeMode[];\n /** Show a tooltip labelling the current action. Defaults to true. */\n tooltip?: boolean;\n}\n\n/**\n * Theme toggle button. Cycles through light → dark → system (follows OS) modes.\n *\n * Reads from and writes to `localStorage` under the key `\"theme\"`. When set to\n * `\"system\"` the key is removed so the OS preference takes over automatically.\n * Applies the resolved mode to `document.documentElement.dataset.mode`.\n *\n * @example\n * ```tsx\n * // Simple uncontrolled — manages localStorage automatically\n * <ThemeToggle />\n *\n * // Controlled\n * const [mode, setMode] = useState<SFThemeMode>(\"system\");\n * <ThemeToggle mode={mode} onModeChange={setMode} />\n *\n * // Light/dark only (no system option)\n * <ThemeToggle cycle={[\"light\", \"dark\"]} />\n * ```\n */\nexport function ThemeToggle({\n className,\n mode: controlledMode,\n onModeChange,\n cycle = [\"light\", \"dark\", \"system\"],\n tooltip = true,\n}: ThemeToggleProps) {\n const isControlled = controlledMode !== undefined;\n\n const [internalMode, setInternalMode] = useState<SFThemeMode>(\"system\");\n const [mounted, setMounted] = useState(false);\n\n // Hydrate from localStorage on mount\n useEffect(() => {\n setMounted(true);\n if (!isControlled) {\n setInternalMode(getStoredThemeMode());\n }\n }, [isControlled]);\n\n // Keep in sync if system preference changes while in \"system\" mode\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const activeMode = isControlled ? controlledMode : internalMode;\n if (activeMode !== \"system\") return;\n\n const handler = () => applyTheme(\"system\");\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, [isControlled, controlledMode, internalMode]);\n\n const activeMode = isControlled ? (controlledMode ?? \"system\") : internalMode;\n const resolvedActive = resolveMode(activeMode);\n\n const handleClick = () => {\n const idx = cycle.indexOf(activeMode);\n const next = cycle[(idx + 1) % cycle.length] ?? cycle[0] ?? \"system\";\n applyTheme(next);\n if (!isControlled) setInternalMode(next);\n onModeChange?.(next);\n };\n\n const tooltipLabel =\n activeMode === \"light\"\n ? \"Switch to dark mode\"\n : activeMode === \"dark\"\n ? \"Use system theme\"\n : \"Switch to light mode\";\n\n // SSR / pre-mount: render a stable placeholder to avoid hydration mismatch\n if (!mounted) {\n return (\n <Button\n aria-label=\"Toggle theme\"\n className={cn(\"text-sf-subtle\", className)}\n shape=\"square\"\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <SunIcon className=\"size-4\" />\n </Button>\n );\n }\n\n const button = (\n <Button\n aria-label={tooltipLabel}\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n onClick={handleClick}\n shape=\"square\"\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n {resolvedActive === \"dark\" ? (\n <MoonIcon className=\"size-4\" />\n ) : (\n <SunIcon className=\"size-4\" />\n )}\n </Button>\n );\n\n if (!tooltip) return button;\n\n return <Tooltip content={tooltipLabel}>{button}</Tooltip>;\n}\n"],"mappings":";;;;;;;;AAaA,IAAa,2BAA2B,EACtC,MAAM;CACJ,OAAO;EAAE,SAAS;EAAI,aAAa;EAAc;CACjD,MAAM;EAAE,SAAS;EAAI,aAAa;EAAa;CAC/C,QAAQ;EAAE,SAAS;EAAI,aAAa;EAA4B;CACjE,EACF;AAED,IAAa,mCAAmC,EAC9C,MAAM,UACP;AAID,IAAM,cAAc;AAEpB,SAAS,iBAAmC;AAC1C,KAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAO,OAAO,WAAW,+BAA+B,CAAC,UACrD,SACA;;AAGN,SAAS,YAAY,MAAqC;AACxD,QAAO,SAAS,WAAW,gBAAgB,GAAG;;AAGhD,SAAS,WAAW,MAAmB;CACrC,MAAM,WAAW,YAAY,KAAK;AAClC,UAAS,gBAAgB,QAAQ,OAAO;AACxC,KAAI,SAAS,SACX,cAAa,WAAW,YAAY;KAEpC,cAAa,QAAQ,aAAa,KAAK;;;;;;AAQ3C,SAAgB,qBAAkC;AAChD,KAAI,OAAO,WAAW,YAAa,QAAO;CAC1C,MAAM,SAAS,aAAa,QAAQ,YAAY;AAChD,KAAI,WAAW,WAAW,WAAW,OAAQ,QAAO;AACpD,QAAO;;;;;;;;;;;;;;;;;;;;;;AA+CT,SAAgB,YAAY,EAC1B,WACA,MAAM,gBACN,cACA,QAAQ;CAAC;CAAS;CAAQ;CAAS,EACnC,UAAU,QACS;CACnB,MAAM,eAAe,mBAAmB,KAAA;CAExC,MAAM,CAAC,cAAc,mBAAmB,SAAsB,SAAS;CACvE,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;AAG7C,iBAAgB;AACd,aAAW,KAAK;AAChB,MAAI,CAAC,aACH,iBAAgB,oBAAoB,CAAC;IAEtC,CAAC,aAAa,CAAC;AAGlB,iBAAgB;AACd,MAAI,OAAO,WAAW,YAAa;EACnC,MAAM,KAAK,OAAO,WAAW,+BAA+B;AAE5D,OADmB,eAAe,iBAAiB,kBAChC,SAAU;EAE7B,MAAM,gBAAgB,WAAW,SAAS;AAC1C,KAAG,iBAAiB,UAAU,QAAQ;AACtC,eAAa,GAAG,oBAAoB,UAAU,QAAQ;IACrD;EAAC;EAAc;EAAgB;EAAa,CAAC;CAEhD,MAAM,aAAa,eAAgB,kBAAkB,WAAY;CACjE,MAAM,iBAAiB,YAAY,WAAW;CAE9C,MAAM,oBAAoB;EAExB,MAAM,OAAO,OADD,MAAM,QAAQ,WAAW,GACX,KAAK,MAAM,WAAW,MAAM,MAAM;AAC5D,aAAW,KAAK;AAChB,MAAI,CAAC,aAAc,iBAAgB,KAAK;AACxC,iBAAe,KAAK;;CAGtB,MAAM,eACJ,eAAe,UACX,wBACA,eAAe,SACb,qBACA;AAGR,KAAI,CAAC,QACH,QACE,oBAAC,QAAD;EACE,cAAW;EACX,WAAW,GAAG,kBAAkB,UAAU;EAC1C,OAAM;EACN,MAAK;EACL,MAAK;EACL,SAAQ;YAER,oBAAC,SAAD,EAAS,WAAU,UAAW,CAAA;EACvB,CAAA;CAIb,MAAM,SACJ,oBAAC,QAAD;EACE,cAAY;EACZ,WAAW,GAAG,wCAAwC,UAAU;EAChE,SAAS;EACT,OAAM;EACN,MAAK;EACL,MAAK;EACL,SAAQ;YAEP,mBAAmB,SAClB,oBAAC,UAAD,EAAU,WAAU,UAAW,CAAA,GAE/B,oBAAC,SAAD,EAAS,WAAU,UAAW,CAAA;EAEzB,CAAA;AAGX,KAAI,CAAC,QAAS,QAAO;AAErB,QAAO,oBAAC,SAAD;EAAS,SAAS;YAAe;EAAiB,CAAA"}
1
+ {"version":3,"file":"theme-toggle-Bhu681D7.js","names":[],"sources":["../src/components/theme-toggle/theme-toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { MoonIcon, SunIcon } from \"@phosphor-icons/react\";\nimport { useEffect, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\nimport { Tooltip } from \"../tooltip\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type SFThemeMode = \"light\" | \"dark\" | \"system\";\n\nexport const SF_THEME_TOGGLE_VARIANTS = {\n mode: {\n light: { classes: \"\", description: \"Light mode\" },\n dark: { classes: \"\", description: \"Dark mode\" },\n system: { classes: \"\", description: \"Follow system preference\" },\n },\n} as const;\n\nexport const SF_THEME_TOGGLE_DEFAULT_VARIANTS = {\n mode: \"system\",\n} as const;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nconst STORAGE_KEY = \"theme\";\n\nfunction getSystemTheme(): \"light\" | \"dark\" {\n if (typeof window === \"undefined\") return \"light\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\";\n}\n\nfunction resolveMode(mode: SFThemeMode): \"light\" | \"dark\" {\n return mode === \"system\" ? getSystemTheme() : mode;\n}\n\nfunction applyTheme(mode: SFThemeMode) {\n const resolved = resolveMode(mode);\n document.documentElement.dataset.mode = resolved;\n if (mode === \"system\") {\n localStorage.removeItem(STORAGE_KEY);\n } else {\n localStorage.setItem(STORAGE_KEY, mode);\n }\n}\n\n/**\n * Read the current persisted mode preference from localStorage.\n * Returns \"system\" if nothing is stored.\n */\nexport function getStoredThemeMode(): SFThemeMode {\n if (typeof window === \"undefined\") return \"system\";\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored === \"light\" || stored === \"dark\") return stored;\n return \"system\";\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport interface ThemeToggleProps {\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /**\n * Controlled mode. When provided the component acts as a controlled input —\n * pair with `onModeChange`.\n */\n mode?: SFThemeMode;\n /**\n * Called when the user cycles to a new mode.\n * Receives the new mode value.\n */\n onModeChange?: (mode: SFThemeMode) => void;\n /**\n * Cycle order for clicking. Defaults to `[\"light\", \"dark\", \"system\"]`.\n * Remove `\"system\"` to limit to a simple light/dark toggle.\n */\n cycle?: SFThemeMode[];\n /** Show a tooltip labelling the current action. Defaults to true. */\n tooltip?: boolean;\n}\n\n/**\n * Theme toggle button. Cycles through light → dark → system (follows OS) modes.\n *\n * Reads from and writes to `localStorage` under the key `\"theme\"`. When set to\n * `\"system\"` the key is removed so the OS preference takes over automatically.\n * Applies the resolved mode to `document.documentElement.dataset.mode`.\n *\n * @example\n * ```tsx\n * // Simple uncontrolled — manages localStorage automatically\n * <ThemeToggle />\n *\n * // Controlled\n * const [mode, setMode] = useState<SFThemeMode>(\"system\");\n * <ThemeToggle mode={mode} onModeChange={setMode} />\n *\n * // Light/dark only (no system option)\n * <ThemeToggle cycle={[\"light\", \"dark\"]} />\n * ```\n */\nexport function ThemeToggle({\n className,\n mode: controlledMode,\n onModeChange,\n cycle = [\"light\", \"dark\", \"system\"],\n tooltip = true,\n}: ThemeToggleProps) {\n const isControlled = controlledMode !== undefined;\n\n const [internalMode, setInternalMode] = useState<SFThemeMode>(\"system\");\n const [mounted, setMounted] = useState(false);\n\n // Hydrate from localStorage on mount\n useEffect(() => {\n setMounted(true);\n if (!isControlled) {\n setInternalMode(getStoredThemeMode());\n }\n }, [isControlled]);\n\n // Keep in sync if system preference changes while in \"system\" mode\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const activeMode = isControlled ? controlledMode : internalMode;\n if (activeMode !== \"system\") return;\n\n const handler = () => applyTheme(\"system\");\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, [isControlled, controlledMode, internalMode]);\n\n const activeMode = isControlled ? (controlledMode ?? \"system\") : internalMode;\n const resolvedActive = resolveMode(activeMode);\n\n const handleClick = () => {\n const idx = cycle.indexOf(activeMode);\n const next = cycle[(idx + 1) % cycle.length] ?? cycle[0] ?? \"system\";\n applyTheme(next);\n if (!isControlled) setInternalMode(next);\n onModeChange?.(next);\n };\n\n const tooltipLabel =\n activeMode === \"light\"\n ? \"Switch to dark mode\"\n : activeMode === \"dark\"\n ? \"Use system theme\"\n : \"Switch to light mode\";\n\n // SSR / pre-mount: render a stable placeholder to avoid hydration mismatch\n if (!mounted) {\n return (\n <Button\n aria-label=\"Toggle theme\"\n className={cn(\"text-sf-subtle\", className)}\n shape=\"square\"\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <SunIcon className=\"size-4\" />\n </Button>\n );\n }\n\n const button = (\n <Button\n aria-label={tooltipLabel}\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n onClick={handleClick}\n shape=\"square\"\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n {resolvedActive === \"dark\" ? (\n <MoonIcon className=\"size-4\" />\n ) : (\n <SunIcon className=\"size-4\" />\n )}\n </Button>\n );\n\n if (!tooltip) return button;\n\n return <Tooltip content={tooltipLabel}>{button}</Tooltip>;\n}\n"],"mappings":";;;;;;;;AAaA,IAAa,2BAA2B,EACtC,MAAM;CACJ,OAAO;EAAE,SAAS;EAAI,aAAa;EAAc;CACjD,MAAM;EAAE,SAAS;EAAI,aAAa;EAAa;CAC/C,QAAQ;EAAE,SAAS;EAAI,aAAa;EAA4B;CACjE,EACF;AAED,IAAa,mCAAmC,EAC9C,MAAM,UACP;AAID,IAAM,cAAc;AAEpB,SAAS,iBAAmC;AAC1C,KAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAO,OAAO,WAAW,+BAA+B,CAAC,UACrD,SACA;;AAGN,SAAS,YAAY,MAAqC;AACxD,QAAO,SAAS,WAAW,gBAAgB,GAAG;;AAGhD,SAAS,WAAW,MAAmB;CACrC,MAAM,WAAW,YAAY,KAAK;AAClC,UAAS,gBAAgB,QAAQ,OAAO;AACxC,KAAI,SAAS,SACX,cAAa,WAAW,YAAY;KAEpC,cAAa,QAAQ,aAAa,KAAK;;;;;;AAQ3C,SAAgB,qBAAkC;AAChD,KAAI,OAAO,WAAW,YAAa,QAAO;CAC1C,MAAM,SAAS,aAAa,QAAQ,YAAY;AAChD,KAAI,WAAW,WAAW,WAAW,OAAQ,QAAO;AACpD,QAAO;;;;;;;;;;;;;;;;;;;;;;AA+CT,SAAgB,YAAY,EAC1B,WACA,MAAM,gBACN,cACA,QAAQ;CAAC;CAAS;CAAQ;CAAS,EACnC,UAAU,QACS;CACnB,MAAM,eAAe,mBAAmB,KAAA;CAExC,MAAM,CAAC,cAAc,mBAAmB,SAAsB,SAAS;CACvE,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;AAG7C,iBAAgB;AACd,aAAW,KAAK;AAChB,MAAI,CAAC,aACH,iBAAgB,oBAAoB,CAAC;IAEtC,CAAC,aAAa,CAAC;AAGlB,iBAAgB;AACd,MAAI,OAAO,WAAW,YAAa;EACnC,MAAM,KAAK,OAAO,WAAW,+BAA+B;AAE5D,OADmB,eAAe,iBAAiB,kBAChC,SAAU;EAE7B,MAAM,gBAAgB,WAAW,SAAS;AAC1C,KAAG,iBAAiB,UAAU,QAAQ;AACtC,eAAa,GAAG,oBAAoB,UAAU,QAAQ;IACrD;EAAC;EAAc;EAAgB;EAAa,CAAC;CAEhD,MAAM,aAAa,eAAgB,kBAAkB,WAAY;CACjE,MAAM,iBAAiB,YAAY,WAAW;CAE9C,MAAM,oBAAoB;EAExB,MAAM,OAAO,OADD,MAAM,QAAQ,WAAW,GACX,KAAK,MAAM,WAAW,MAAM,MAAM;AAC5D,aAAW,KAAK;AAChB,MAAI,CAAC,aAAc,iBAAgB,KAAK;AACxC,iBAAe,KAAK;;CAGtB,MAAM,eACJ,eAAe,UACX,wBACA,eAAe,SACb,qBACA;AAGR,KAAI,CAAC,QACH,QACE,oBAAC,QAAD;EACE,cAAW;EACX,WAAW,GAAG,kBAAkB,UAAU;EAC1C,OAAM;EACN,MAAK;EACL,MAAK;EACL,SAAQ;YAER,oBAAC,SAAD,EAAS,WAAU,UAAW,CAAA;EACvB,CAAA;CAIb,MAAM,SACJ,oBAAC,QAAD;EACE,cAAY;EACZ,WAAW,GAAG,wCAAwC,UAAU;EAChE,SAAS;EACT,OAAM;EACN,MAAK;EACL,MAAK;EACL,SAAQ;YAEP,mBAAmB,SAClB,oBAAC,UAAD,EAAU,WAAU,UAAW,CAAA,GAE/B,oBAAC,SAAD,EAAS,WAAU,UAAW,CAAA;EAEzB,CAAA;AAGX,KAAI,CAAC,QAAS,QAAO;AAErB,QAAO,oBAAC,SAAD;EAAS,SAAS;YAAe;EAAiB,CAAA"}
@@ -4,9 +4,9 @@ import { useCallback, useEffect, useReducer, useRef } from "react";
4
4
  var SF_USE_AGENT_HARNESS_VARIANTS = {};
5
5
  var SF_USE_AGENT_HARNESS_DEFAULT_VARIANTS = {};
6
6
  /**
7
- * Translate a Mastra HarnessEvent into one or more SF HarnessEvents.
7
+ * Translate a Mastra HarnessEvent into one or more SignalFlare HarnessEvents.
8
8
  *
9
- * Mastra sends full HarnessMessage objects on message_update/end, while SF
9
+ * Mastra sends full HarnessMessage objects on message_update/end, while SignalFlare
10
10
  * expects incremental deltas + separate thinking events. This function
11
11
  * bridges the gap.
12
12
  */
@@ -82,10 +82,10 @@ function translateMastraEvent(mastraEvent, prevMessages) {
82
82
  return [mastraEvent];
83
83
  }
84
84
  /**
85
- * Wrap a Mastra `Harness` instance as an SF `HarnessAdapter`.
85
+ * Wrap a Mastra `Harness` instance as a SignalFlare `HarnessAdapter`.
86
86
  *
87
87
  * Translates Mastra's event format (full `HarnessMessage` objects on
88
- * `message_update`) into SF's incremental event protocol, and extracts
88
+ * `message_update`) into SignalFlare's incremental event protocol, and extracts
89
89
  * `thinking` content parts into `thinking_start/delta/end` events so the
90
90
  * `AgentHarness` block can render them as collapsible reasoning blocks.
91
91
  */
@@ -926,4 +926,4 @@ function useAgentHarness({ adapter }) {
926
926
  //#endregion
927
927
  export { useAgentHarness as a, fromMastraHarness as i, SF_USE_AGENT_HARNESS_VARIANTS as n, createAgentHarnessState as r, SF_USE_AGENT_HARNESS_DEFAULT_VARIANTS as t };
928
928
 
929
- //# sourceMappingURL=use-agent-harness-DZzcn96L.js.map
929
+ //# sourceMappingURL=use-agent-harness-BMyF8pTq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-agent-harness-BMyF8pTq.js","names":[],"sources":["../src/components/use-agent-harness/use-agent-harness.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useReducer, useRef } from \"react\";\n\n// ─── Variants (required by SignalFlare conventions) ───────────────────────────────────\n\nexport const SF_USE_AGENT_HARNESS_VARIANTS = {} as const;\nexport const SF_USE_AGENT_HARNESS_DEFAULT_VARIANTS = {} as const;\n\n// ─── Harness Event Types ──────────────────────────────────────────────────────\n\n/** All event types emitted by a Mastra Harness instance. */\nexport type HarnessEventType =\n | \"mode_changed\"\n | \"model_changed\"\n | \"thread_changed\"\n | \"thread_created\"\n | \"thread_deleted\"\n | \"state_changed\"\n | \"agent_start\"\n | \"agent_end\"\n | \"message_start\"\n | \"message_update\"\n | \"message_end\"\n | \"tool_start\"\n | \"tool_approval_required\"\n | \"tool_update\"\n | \"tool_end\"\n | \"tool_input_start\"\n | \"tool_input_delta\"\n | \"tool_input_end\"\n | \"usage_update\"\n | \"error\"\n | \"info\"\n | \"follow_up_queued\"\n | \"workspace_status_changed\"\n | \"workspace_ready\"\n | \"workspace_error\"\n | \"om_status\"\n | \"om_observation_start\"\n | \"om_observation_end\"\n | \"om_reflection_start\"\n | \"om_reflection_end\"\n | \"ask_question\"\n | \"question_answered\"\n | \"plan_approval_required\"\n | \"plan_approved\"\n | \"subagent_start\"\n | \"subagent_text_delta\"\n | \"subagent_tool_start\"\n | \"subagent_tool_end\"\n | \"subagent_end\"\n | \"subagent_model_changed\"\n | \"task_updated\"\n | \"thinking_start\"\n | \"thinking_delta\"\n | \"thinking_end\";\n\n/** Base shape of all harness events. */\nexport interface HarnessEventBase {\n type: HarnessEventType;\n}\n\nexport interface HarnessModeChangedEvent extends HarnessEventBase {\n type: \"mode_changed\";\n modeId: string;\n modeName: string;\n}\n\nexport interface HarnessModelChangedEvent extends HarnessEventBase {\n type: \"model_changed\";\n modelId: string;\n modelName?: string;\n}\n\nexport interface HarnessThreadChangedEvent extends HarnessEventBase {\n type: \"thread_changed\";\n threadId: string;\n}\n\nexport interface HarnessThreadCreatedEvent extends HarnessEventBase {\n type: \"thread_created\";\n threadId: string;\n}\n\nexport interface HarnessThreadDeletedEvent extends HarnessEventBase {\n type: \"thread_deleted\";\n threadId: string;\n}\n\nexport interface HarnessStateChangedEvent extends HarnessEventBase {\n type: \"state_changed\";\n state: Record<string, unknown>;\n changedKeys: string[];\n}\n\nexport interface HarnessAgentStartEvent extends HarnessEventBase {\n type: \"agent_start\";\n}\n\nexport interface HarnessAgentEndEvent extends HarnessEventBase {\n type: \"agent_end\";\n}\n\nexport interface HarnessMessageStartEvent extends HarnessEventBase {\n type: \"message_start\";\n messageId: string;\n role: \"assistant\" | \"user\" | \"system\";\n}\n\nexport interface HarnessMessageUpdateEvent extends HarnessEventBase {\n type: \"message_update\";\n messageId: string;\n delta: string;\n content?: string;\n}\n\nexport interface HarnessMessageEndEvent extends HarnessEventBase {\n type: \"message_end\";\n messageId: string;\n content: string;\n}\n\nexport interface HarnessToolStartEvent extends HarnessEventBase {\n type: \"tool_start\";\n toolCallId: string;\n toolName: string;\n messageId?: string;\n subagentId?: string;\n}\n\nexport interface HarnessToolApprovalRequiredEvent extends HarnessEventBase {\n type: \"tool_approval_required\";\n toolCallId: string;\n toolName: string;\n input?: unknown;\n messageId?: string;\n}\n\nexport interface HarnessToolUpdateEvent extends HarnessEventBase {\n type: \"tool_update\";\n toolCallId: string;\n summary?: string;\n progress?: number;\n}\n\nexport interface HarnessToolEndEvent extends HarnessEventBase {\n type: \"tool_end\";\n toolCallId: string;\n output?: unknown;\n error?: string;\n durationMs?: number;\n}\n\nexport interface HarnessToolInputStartEvent extends HarnessEventBase {\n type: \"tool_input_start\";\n toolCallId: string;\n}\n\nexport interface HarnessToolInputDeltaEvent extends HarnessEventBase {\n type: \"tool_input_delta\";\n toolCallId: string;\n delta: string;\n}\n\nexport interface HarnessToolInputEndEvent extends HarnessEventBase {\n type: \"tool_input_end\";\n toolCallId: string;\n input: unknown;\n}\n\nexport interface HarnessUsageUpdateEvent extends HarnessEventBase {\n type: \"usage_update\";\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n cost?: number;\n modelId?: string;\n}\n\nexport interface HarnessErrorEvent extends HarnessEventBase {\n type: \"error\";\n error: string | Error;\n messageId?: string;\n}\n\nexport interface HarnessInfoEvent extends HarnessEventBase {\n type: \"info\";\n message: string;\n}\n\nexport interface HarnessFollowUpQueuedEvent extends HarnessEventBase {\n type: \"follow_up_queued\";\n content: string;\n}\n\nexport interface HarnessWorkspaceStatusChangedEvent extends HarnessEventBase {\n type: \"workspace_status_changed\";\n status: string;\n}\n\nexport interface HarnessWorkspaceReadyEvent extends HarnessEventBase {\n type: \"workspace_ready\";\n}\n\nexport interface HarnessWorkspaceErrorEvent extends HarnessEventBase {\n type: \"workspace_error\";\n error: string | Error;\n}\n\nexport interface HarnessOMStatusEvent extends HarnessEventBase {\n type: \"om_status\";\n generationCount?: number;\n observationTokenCount?: number;\n activeObservations?: number;\n}\n\nexport interface HarnessOMObservationStartEvent extends HarnessEventBase {\n type: \"om_observation_start\";\n observationId?: string;\n}\n\nexport interface HarnessOMObservationEndEvent extends HarnessEventBase {\n type: \"om_observation_end\";\n observationId?: string;\n text?: string;\n durationMs?: number;\n}\n\nexport interface HarnessOMReflectionStartEvent extends HarnessEventBase {\n type: \"om_reflection_start\";\n}\n\nexport interface HarnessOMReflectionEndEvent extends HarnessEventBase {\n type: \"om_reflection_end\";\n text?: string;\n durationMs?: number;\n}\n\nexport interface HarnessAskQuestionEvent extends HarnessEventBase {\n type: \"ask_question\";\n questionId: string;\n question: string;\n header?: string;\n options?: Array<{ label: string; description?: string }>;\n multiple?: boolean;\n allowCustom?: boolean;\n}\n\nexport interface HarnessQuestionAnsweredEvent extends HarnessEventBase {\n type: \"question_answered\";\n questionId: string;\n answer: string;\n}\n\nexport interface HarnessPlanApprovalRequiredEvent extends HarnessEventBase {\n type: \"plan_approval_required\";\n planId: string;\n title: string;\n description?: string;\n steps?: Array<{ id: string; label: string; description?: string }>;\n}\n\nexport interface HarnessPlanApprovedEvent extends HarnessEventBase {\n type: \"plan_approved\";\n planId: string;\n}\n\nexport interface HarnessSubagentStartEvent extends HarnessEventBase {\n type: \"subagent_start\";\n subagentId: string;\n agentType?: string;\n name?: string;\n modelId?: string;\n parentMessageId?: string;\n}\n\nexport interface HarnessSubagentTextDeltaEvent extends HarnessEventBase {\n type: \"subagent_text_delta\";\n subagentId: string;\n delta: string;\n}\n\nexport interface HarnessSubagentToolStartEvent extends HarnessEventBase {\n type: \"subagent_tool_start\";\n subagentId: string;\n toolCallId: string;\n toolName: string;\n}\n\nexport interface HarnessSubagentToolEndEvent extends HarnessEventBase {\n type: \"subagent_tool_end\";\n subagentId: string;\n toolCallId: string;\n output?: unknown;\n error?: string;\n durationMs?: number;\n}\n\nexport interface HarnessSubagentEndEvent extends HarnessEventBase {\n type: \"subagent_end\";\n subagentId: string;\n error?: string;\n durationMs?: number;\n}\n\nexport interface HarnessSubagentModelChangedEvent extends HarnessEventBase {\n type: \"subagent_model_changed\";\n subagentId?: string;\n modelId: string;\n agentType?: string;\n}\n\nexport interface HarnessTaskUpdatedEvent extends HarnessEventBase {\n type: \"task_updated\";\n tasks: Array<{\n id: string;\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\" | \"cancelled\";\n priority?: \"high\" | \"medium\" | \"low\";\n }>;\n title?: string;\n}\n\n/** Emitted when the model begins a thinking/reasoning block. */\nexport interface HarnessThinkingStartEvent extends HarnessEventBase {\n type: \"thinking_start\";\n thinkingId: string;\n messageId: string;\n}\n\n/** Emitted for each incremental chunk of thinking text. */\nexport interface HarnessThinkingDeltaEvent extends HarnessEventBase {\n type: \"thinking_delta\";\n thinkingId: string;\n messageId: string;\n /** Incremental text to append. */\n delta: string;\n /** Full text so far (if available). */\n content?: string;\n}\n\n/** Emitted when a thinking block is complete. */\nexport interface HarnessThinkingEndEvent extends HarnessEventBase {\n type: \"thinking_end\";\n thinkingId: string;\n messageId: string;\n /** Final accumulated thinking text. */\n content: string;\n}\n\n/** Union of all typed harness events. */\nexport type HarnessEvent =\n | HarnessModeChangedEvent\n | HarnessModelChangedEvent\n | HarnessThreadChangedEvent\n | HarnessThreadCreatedEvent\n | HarnessThreadDeletedEvent\n | HarnessStateChangedEvent\n | HarnessAgentStartEvent\n | HarnessAgentEndEvent\n | HarnessMessageStartEvent\n | HarnessMessageUpdateEvent\n | HarnessMessageEndEvent\n | HarnessToolStartEvent\n | HarnessToolApprovalRequiredEvent\n | HarnessToolUpdateEvent\n | HarnessToolEndEvent\n | HarnessToolInputStartEvent\n | HarnessToolInputDeltaEvent\n | HarnessToolInputEndEvent\n | HarnessUsageUpdateEvent\n | HarnessErrorEvent\n | HarnessInfoEvent\n | HarnessFollowUpQueuedEvent\n | HarnessWorkspaceStatusChangedEvent\n | HarnessWorkspaceReadyEvent\n | HarnessWorkspaceErrorEvent\n | HarnessOMStatusEvent\n | HarnessOMObservationStartEvent\n | HarnessOMObservationEndEvent\n | HarnessOMReflectionStartEvent\n | HarnessOMReflectionEndEvent\n | HarnessAskQuestionEvent\n | HarnessQuestionAnsweredEvent\n | HarnessPlanApprovalRequiredEvent\n | HarnessPlanApprovedEvent\n | HarnessSubagentStartEvent\n | HarnessSubagentTextDeltaEvent\n | HarnessSubagentToolStartEvent\n | HarnessSubagentToolEndEvent\n | HarnessSubagentEndEvent\n | HarnessSubagentModelChangedEvent\n | HarnessTaskUpdatedEvent\n | HarnessThinkingStartEvent\n | HarnessThinkingDeltaEvent\n | HarnessThinkingEndEvent;\n\n// ─── Adapter Interface ────────────────────────────────────────────────────────\n\n/**\n * Minimal adapter interface for driving the AgentHarness UI.\n * Implement this to connect any event source — Mastra Harness, mock, replay, etc.\n */\nexport interface HarnessAdapter {\n /** Register an event listener. Returns an unsubscribe function. */\n subscribe: (listener: (event: HarnessEvent) => void) => () => void;\n /** Send a user message. */\n sendMessage: (params: {\n content: string;\n files?: Array<{ url: string; mediaType: string; filename: string }>;\n }) => void | Promise<void>;\n /** Respond to a pending tool approval. */\n respondToToolApproval?: (params: {\n decision: \"approve\" | \"decline\";\n }) => void | Promise<void>;\n /** Respond to a pending question. */\n respondToQuestion?: (params: {\n questionId: string;\n answer: string;\n }) => void | Promise<void>;\n /** Respond to a pending plan approval. */\n respondToPlanApproval?: (params: {\n planId: string;\n response: { action: \"approved\" | \"rejected\"; feedback?: string };\n }) => void | Promise<void>;\n /** Abort any in-progress generation. */\n abort?: () => void;\n /** Steer the agent mid-stream. */\n steer?: (params: { content: string }) => void;\n /** Select a mode. */\n selectMode?: (params: { modeId: string }) => void | Promise<void>;\n}\n\n/**\n * Create a HarnessAdapter from a real Mastra Harness instance.\n * The Mastra harness type is not imported to avoid a hard dependency.\n */\n// ─── Mastra → SignalFlare event translation ───────────────────────────────────────────\n\n/** Mastra's HarnessMessage content part (subset we care about). */\ntype MastraContentPart =\n | { type: \"text\"; text: string }\n | { type: \"thinking\"; thinking: string }\n | { type: \"tool_call\"; id: string; name: string; args: unknown }\n | { type: string; [key: string]: unknown };\n\n/** Mastra's HarnessMessage shape (from @mastra/core). */\ninterface MastraHarnessMessage {\n id: string;\n role: \"user\" | \"assistant\" | \"system\";\n content: MastraContentPart[];\n createdAt: Date;\n stopReason?: \"complete\" | \"tool_use\" | \"aborted\" | \"error\";\n}\n\n/** Mastra's raw HarnessEvent union (only the fields we translate). */\ntype MastraHarnessEvent =\n | { type: \"message_start\"; message: MastraHarnessMessage }\n | { type: \"message_update\"; message: MastraHarnessMessage }\n | { type: \"message_end\"; message: MastraHarnessMessage }\n | { type: string; [key: string]: unknown };\n\n/**\n * Translate a Mastra HarnessEvent into one or more SignalFlare HarnessEvents.\n *\n * Mastra sends full HarnessMessage objects on message_update/end, while SignalFlare\n * expects incremental deltas + separate thinking events. This function\n * bridges the gap.\n */\nfunction translateMastraEvent(\n mastraEvent: MastraHarnessEvent,\n prevMessages: Map<string, MastraHarnessMessage>\n): HarnessEvent[] {\n const out: HarnessEvent[] = [];\n\n if (\n mastraEvent.type === \"message_start\" ||\n mastraEvent.type === \"message_update\" ||\n mastraEvent.type === \"message_end\"\n ) {\n // TypeScript needs an explicit cast here because the catch-all arm in\n // MastraHarnessEvent doesn't carry `.message`. We've already narrowed via type.\n const msg = (\n mastraEvent as {\n type: \"message_start\" | \"message_update\" | \"message_end\";\n message: MastraHarnessMessage;\n }\n ).message;\n const prev = prevMessages.get(msg.id);\n\n if (mastraEvent.type === \"message_start\") {\n out.push({ type: \"message_start\", messageId: msg.id, role: msg.role });\n }\n\n // Extract text and thinking parts from content array\n const textParts = msg.content.filter(\n (p): p is { type: \"text\"; text: string } => p.type === \"text\"\n );\n const thinkingParts = msg.content.filter(\n (p): p is { type: \"thinking\"; thinking: string } => p.type === \"thinking\"\n );\n\n const fullText = textParts.map((p) => p.text).join(\"\");\n const prevText = prev\n ? prev.content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\")\n : \"\";\n\n // Emit thinking blocks — each thinking part gets its own thinking_start/end\n // We compare against previous to only emit new/changed thinking blocks\n const prevThinking = prev\n ? prev.content.filter(\n (p): p is { type: \"thinking\"; thinking: string } =>\n p.type === \"thinking\"\n )\n : [];\n\n thinkingParts.forEach((part, i) => {\n const thinkingId = `${msg.id}-thinking-${i}`;\n const prevPart = prevThinking[i];\n if (!prevPart) {\n // New thinking block\n out.push({ type: \"thinking_start\", thinkingId, messageId: msg.id });\n if (part.thinking) {\n out.push({\n type: \"thinking_delta\",\n thinkingId,\n messageId: msg.id,\n delta: part.thinking,\n content: part.thinking,\n });\n }\n } else if (part.thinking !== prevPart.thinking) {\n // Updated thinking block — emit delta\n const delta = part.thinking.slice(prevPart.thinking.length);\n if (delta) {\n out.push({\n type: \"thinking_delta\",\n thinkingId,\n messageId: msg.id,\n delta,\n content: part.thinking,\n });\n }\n }\n });\n\n // Emit text delta if content changed\n if (fullText !== prevText && mastraEvent.type !== \"message_start\") {\n const delta = fullText.slice(prevText.length);\n out.push({\n type: \"message_update\",\n messageId: msg.id,\n delta,\n content: fullText,\n });\n }\n\n if (mastraEvent.type === \"message_end\") {\n // Finalize all thinking blocks\n thinkingParts.forEach((part, i) => {\n out.push({\n type: \"thinking_end\",\n thinkingId: `${msg.id}-thinking-${i}`,\n messageId: msg.id,\n content: part.thinking,\n });\n });\n out.push({ type: \"message_end\", messageId: msg.id, content: fullText });\n }\n\n prevMessages.set(msg.id, msg);\n return out;\n }\n\n // Pass through all other events as-is (they match SignalFlare's shape)\n return [mastraEvent as unknown as HarnessEvent];\n}\n\n/**\n * Wrap a Mastra `Harness` instance as a SignalFlare `HarnessAdapter`.\n *\n * Translates Mastra's event format (full `HarnessMessage` objects on\n * `message_update`) into SignalFlare's incremental event protocol, and extracts\n * `thinking` content parts into `thinking_start/delta/end` events so the\n * `AgentHarness` block can render them as collapsible reasoning blocks.\n */\nexport function fromMastraHarness(harness: {\n subscribe: (listener: (event: MastraHarnessEvent) => void) => () => void;\n sendMessage: (params: { content: string }) => void | Promise<void>;\n respondToToolApproval?: (params: {\n decision: \"approve\" | \"decline\";\n }) => void | Promise<void>;\n respondToQuestion?: (params: {\n questionId: string;\n answer: string;\n }) => void | Promise<void>;\n respondToPlanApproval?: (params: {\n planId: string;\n response: { action: \"approved\" | \"rejected\"; feedback?: string };\n }) => void | Promise<void>;\n abort?: () => void;\n steer?: (params: { content: string }) => void;\n selectMode?: (params: { modeId: string }) => void | Promise<void>;\n}): HarnessAdapter {\n return {\n subscribe(listener: (event: HarnessEvent) => void) {\n // Per-subscription message state for delta tracking\n const prevMessages = new Map<string, MastraHarnessMessage>();\n return harness.subscribe((mastraEvent) => {\n const translated = translateMastraEvent(mastraEvent, prevMessages);\n for (const ev of translated) listener(ev);\n });\n },\n sendMessage: harness.sendMessage.bind(harness),\n respondToToolApproval: harness.respondToToolApproval?.bind(harness),\n respondToQuestion: harness.respondToQuestion?.bind(harness),\n respondToPlanApproval: harness.respondToPlanApproval?.bind(harness),\n abort: harness.abort?.bind(harness),\n steer: harness.steer\n ? (params: { content: string }) => harness.steer!(params)\n : undefined,\n selectMode: harness.selectMode\n ? (params: { modeId: string }) => harness.selectMode!(params)\n : undefined,\n };\n}\n\n// ─── State Types ──────────────────────────────────────────────────────────────\n\n/** A single message in the conversation. */\nexport interface AgentMessage {\n id: string;\n role: \"user\" | \"assistant\" | \"system\";\n /** Accumulated text content. */\n content: string;\n /** Whether this message is currently streaming. */\n isStreaming: boolean;\n /** Tool calls attached to this message. */\n toolCallIds: string[];\n /** Subagent IDs spawned during this message. */\n subagentIds: string[];\n /** Thinking block IDs attached to this message (in order). */\n thinkingIds: string[];\n /** Whether this message has an active OM observation. */\n hasOMActivity: boolean;\n /** Whether this message has an approval request. */\n approvalMessageId?: string;\n /** Whether this message has a question. */\n questionId?: string;\n /** Whether this message has a plan approval. */\n planId?: string;\n}\n\n/** A model thinking/reasoning block attached to a message. */\nexport interface AgentThinking {\n id: string;\n /** Parent message ID. */\n messageId: string;\n /** Accumulated thinking text. */\n text: string;\n /** Whether this block is still streaming. */\n isStreaming: boolean;\n}\n\n/** Normalized tool call state. */\nexport interface AgentToolCall {\n id: string;\n toolName: string;\n /** Parent message ID (undefined if inside a subagent). */\n messageId?: string;\n /** Parent subagent ID (undefined if top-level). */\n subagentId?: string;\n state:\n | \"input-streaming\"\n | \"input-available\"\n | \"approval-requested\"\n | \"approval-responded\"\n | \"output-available\"\n | \"output-error\"\n | \"output-denied\";\n input?: unknown;\n inputBuffer?: string;\n output?: unknown;\n errorText?: string;\n summary?: string;\n durationMs?: number;\n approvalState?: \"awaiting\" | \"approved\" | \"declined\";\n /** Wall-clock ms when this tool call started. */\n startedAt?: number;\n /** Wall-clock ms when this tool call ended. */\n endedAt?: number;\n}\n\n/** Normalized subagent state. */\nexport interface AgentSubagent {\n id: string;\n agentType?: string;\n name?: string;\n modelId?: string;\n status: \"running\" | \"completed\" | \"error\";\n /** Accumulated text deltas. */\n content: string;\n /** Tool call IDs inside this subagent. */\n toolCallIds: string[];\n /** Parent message ID. */\n messageId?: string;\n durationMs?: number;\n error?: string;\n /** Wall-clock ms when this subagent started. */\n startedAt?: number;\n /** Wall-clock ms when this subagent ended. */\n endedAt?: number;\n}\n\n/** Observational memory activity item. */\nexport interface AgentOMActivity {\n id: string;\n type: \"observation\" | \"reflection\";\n status: \"streaming\" | \"completed\";\n text?: string;\n durationMs?: number;\n /** Which message this OM activity is attached to. */\n messageId?: string;\n}\n\n/** A pending question. */\nexport interface AgentQuestion {\n questionId: string;\n question: string;\n header?: string;\n options?: Array<{ label: string; description?: string }>;\n multiple?: boolean;\n allowCustom?: boolean;\n status: \"pending\" | \"answered\";\n answeredWith?: string;\n}\n\n/** A pending plan approval. */\nexport interface AgentPlanApproval {\n planId: string;\n title: string;\n description?: string;\n steps?: Array<{ id: string; label: string; description?: string }>;\n status: \"pending\" | \"approved\" | \"rejected\";\n}\n\n/** Task list state. */\nexport interface AgentTaskList {\n title?: string;\n tasks: Array<{\n id: string;\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\" | \"cancelled\";\n priority?: \"high\" | \"medium\" | \"low\";\n }>;\n}\n\n/** Usage/token stats. */\nexport interface AgentUsage {\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n cost?: number;\n modelId?: string;\n}\n\n/** A notice/banner in the conversation. */\nexport interface AgentNotice {\n id: string;\n level: \"info\" | \"error\" | \"change\";\n message: string;\n /** Attach to a message ID for inline rendering, or undefined for standalone. */\n messageId?: string;\n}\n\n/** Full normalized harness UI state. */\nexport interface AgentHarnessState {\n /** Ordered list of message IDs. */\n messageIds: string[];\n /** Message map. */\n messages: Record<string, AgentMessage>;\n /** Tool call map. */\n toolCalls: Record<string, AgentToolCall>;\n /** Subagent map. */\n subagents: Record<string, AgentSubagent>;\n /** OM activity map. */\n omActivities: Record<string, AgentOMActivity>;\n /** Model thinking/reasoning blocks map. */\n thinkings: Record<string, AgentThinking>;\n /** Question map (by questionId). */\n questions: Record<string, AgentQuestion>;\n /** Plan approval map (by planId). */\n planApprovals: Record<string, AgentPlanApproval>;\n /** Notices/banners (inline in conversation). */\n notices: AgentNotice[];\n /** Current task list. */\n taskList: AgentTaskList | null;\n /** Token usage. */\n usage: AgentUsage | null;\n /** Whether the agent is currently running. */\n isRunning: boolean;\n /** Active mode. */\n modeId?: string;\n modeName?: string;\n /** Active model. */\n modelId?: string;\n modelName?: string;\n /** Active thread. */\n threadId?: string;\n /** Active pending tool approval (toolCallId). */\n pendingToolApprovalId?: string;\n /** Active pending question ID. */\n pendingQuestionId?: string;\n /** Active pending plan ID. */\n pendingPlanId?: string;\n /** Whether a workspace error is active. */\n workspaceError?: string;\n /**\n * Wall-clock ms when agent_start fired. Used by Commander timeline.\n * Resets on agent_start; cleared on RESET.\n */\n missionStartedAt?: number;\n /** Wall-clock ms when agent_end fired for the last run. */\n missionEndedAt?: number;\n /**\n * Ordered log of every event with its wall-clock timestamp.\n * Used by the Commander timeline to position blocks accurately.\n * Not rendered by AgentHarness — Commander reads it directly.\n */\n timeline: TimestampedHarnessEvent[];\n}\n\n/** A harness event stamped with the wall-clock time it was received. */\nexport interface TimestampedHarnessEvent {\n event: HarnessEvent;\n /** Date.now() at the moment the event was dispatched into the reducer. */\n timestamp: number;\n}\n\n// ─── Reducer ──────────────────────────────────────────────────────────────────\n\nconst initialState: AgentHarnessState = {\n messageIds: [],\n messages: {},\n toolCalls: {},\n subagents: {},\n omActivities: {},\n thinkings: {},\n questions: {},\n planApprovals: {},\n notices: [],\n taskList: null,\n usage: null,\n isRunning: false,\n timeline: [],\n};\n\n/**\n * Create an empty `AgentHarnessState` with optional partial overrides.\n *\n * Use this when operating in controlled mode — build or derive your own state\n * that conforms to `AgentHarnessState` and pass it directly to `<AgentHarness state={...} />`.\n *\n * @example\n * ```ts\n * const [state, setState] = useState(() => createAgentHarnessState());\n * ```\n */\nexport function createAgentHarnessState(\n partial?: Partial<AgentHarnessState>\n): AgentHarnessState {\n return { ...initialState, ...partial };\n}\n\nlet _noticeCounter = 0;\nfunction nextNoticeId() {\n return `notice-${++_noticeCounter}`;\n}\n\nfunction getErrorString(error: string | Error): string {\n return typeof error === \"string\" ? error : error.message;\n}\n\ntype AgentHarnessAction =\n | { type: \"EVENT\"; event: HarnessEvent; timestamp: number }\n | { type: \"RESET\" };\n\nfunction agentHarnessReducer(\n state: AgentHarnessState,\n action: AgentHarnessAction\n): AgentHarnessState {\n if (action.type === \"RESET\") return { ...initialState };\n\n const { event, timestamp } = action;\n\n // Append every event to the timeline log\n const timeline: TimestampedHarnessEvent[] = [\n ...state.timeline,\n { event, timestamp },\n ];\n\n switch (event.type) {\n // ── Agent lifecycle ─────────────────────────────────────────────────────\n case \"agent_start\":\n return {\n ...state,\n timeline,\n isRunning: true,\n missionStartedAt: state.missionStartedAt ?? timestamp,\n };\n\n case \"agent_end\":\n return {\n ...state,\n timeline,\n isRunning: false,\n missionEndedAt: timestamp,\n };\n\n // ── Message lifecycle ───────────────────────────────────────────────────\n case \"message_start\": {\n const msg: AgentMessage = {\n id: event.messageId,\n role: event.role,\n content: \"\",\n isStreaming: event.role === \"assistant\",\n toolCallIds: [],\n subagentIds: [],\n thinkingIds: [],\n hasOMActivity: false,\n };\n return {\n ...state,\n timeline,\n messageIds: [...state.messageIds, event.messageId],\n messages: { ...state.messages, [event.messageId]: msg },\n };\n }\n\n case \"message_update\": {\n const existing = state.messages[event.messageId];\n if (!existing) return { ...state, timeline };\n const newContent =\n event.content !== undefined\n ? event.content\n : existing.content + event.delta;\n return {\n ...state,\n timeline,\n messages: {\n ...state.messages,\n [event.messageId]: { ...existing, content: newContent },\n },\n };\n }\n\n case \"message_end\": {\n const existing = state.messages[event.messageId];\n if (!existing) return { ...state, timeline };\n return {\n ...state,\n timeline,\n messages: {\n ...state.messages,\n [event.messageId]: {\n ...existing,\n content: event.content,\n isStreaming: false,\n },\n },\n };\n }\n\n // ── Tool calls ──────────────────────────────────────────────────────────\n case \"tool_start\": {\n const toolCall: AgentToolCall = {\n id: event.toolCallId,\n toolName: event.toolName,\n messageId: event.messageId,\n subagentId: event.subagentId,\n state: \"input-streaming\",\n inputBuffer: \"\",\n startedAt: timestamp,\n };\n const updatedMessages = event.messageId\n ? {\n ...state.messages,\n [event.messageId]: {\n ...state.messages[event.messageId],\n toolCallIds: [\n ...(state.messages[event.messageId]?.toolCallIds ?? []),\n event.toolCallId,\n ],\n },\n }\n : state.messages;\n const updatedSubagents =\n event.subagentId && state.subagents[event.subagentId]\n ? {\n ...state.subagents,\n [event.subagentId]: {\n ...state.subagents[event.subagentId],\n toolCallIds: [\n ...state.subagents[event.subagentId].toolCallIds,\n event.toolCallId,\n ],\n },\n }\n : state.subagents;\n return {\n ...state,\n timeline,\n messages: updatedMessages,\n subagents: updatedSubagents,\n toolCalls: { ...state.toolCalls, [event.toolCallId]: toolCall },\n };\n }\n\n case \"tool_input_start\": {\n const tc = state.toolCalls[event.toolCallId];\n if (!tc) return { ...state, timeline };\n return {\n ...state,\n timeline,\n toolCalls: {\n ...state.toolCalls,\n [event.toolCallId]: {\n ...tc,\n state: \"input-streaming\",\n inputBuffer: \"\",\n },\n },\n };\n }\n\n case \"tool_input_delta\": {\n const tc = state.toolCalls[event.toolCallId];\n if (!tc) return { ...state, timeline };\n return {\n ...state,\n timeline,\n toolCalls: {\n ...state.toolCalls,\n [event.toolCallId]: {\n ...tc,\n inputBuffer: (tc.inputBuffer ?? \"\") + event.delta,\n },\n },\n };\n }\n\n case \"tool_input_end\": {\n const tc = state.toolCalls[event.toolCallId];\n if (!tc) return { ...state, timeline };\n return {\n ...state,\n timeline,\n toolCalls: {\n ...state.toolCalls,\n [event.toolCallId]: {\n ...tc,\n state: \"input-available\",\n input: event.input,\n inputBuffer: undefined,\n },\n },\n };\n }\n\n case \"tool_approval_required\": {\n const tc = state.toolCalls[event.toolCallId] ?? {\n id: event.toolCallId,\n toolName: event.toolName,\n messageId: event.messageId,\n state: \"approval-requested\" as const,\n toolCallIds: [],\n startedAt: timestamp,\n };\n return {\n ...state,\n timeline,\n pendingToolApprovalId: event.toolCallId,\n toolCalls: {\n ...state.toolCalls,\n [event.toolCallId]: {\n ...tc,\n state: \"approval-requested\",\n input: event.input ?? tc.input,\n approvalState: \"awaiting\",\n },\n },\n };\n }\n\n case \"tool_update\": {\n const tc = state.toolCalls[event.toolCallId];\n if (!tc) return { ...state, timeline };\n return {\n ...state,\n timeline,\n toolCalls: {\n ...state.toolCalls,\n [event.toolCallId]: { ...tc, summary: event.summary ?? tc.summary },\n },\n };\n }\n\n case \"tool_end\": {\n const tc = state.toolCalls[event.toolCallId];\n if (!tc) return { ...state, timeline };\n const pendingApprovalId =\n state.pendingToolApprovalId === event.toolCallId\n ? undefined\n : state.pendingToolApprovalId;\n return {\n ...state,\n timeline,\n pendingToolApprovalId: pendingApprovalId,\n toolCalls: {\n ...state.toolCalls,\n [event.toolCallId]: {\n ...tc,\n state: event.error ? \"output-error\" : \"output-available\",\n output: event.output,\n errorText: event.error,\n durationMs: event.durationMs,\n endedAt: timestamp,\n },\n },\n };\n }\n\n // ── Subagents ───────────────────────────────────────────────────────────\n case \"subagent_start\": {\n const subagent: AgentSubagent = {\n id: event.subagentId,\n agentType: event.agentType,\n name: event.name,\n modelId: event.modelId,\n status: \"running\",\n content: \"\",\n toolCallIds: [],\n messageId: event.parentMessageId,\n startedAt: timestamp,\n };\n const updatedMessages = event.parentMessageId\n ? {\n ...state.messages,\n [event.parentMessageId]: {\n ...state.messages[event.parentMessageId],\n subagentIds: [\n ...(state.messages[event.parentMessageId]?.subagentIds ?? []),\n event.subagentId,\n ],\n },\n }\n : state.messages;\n return {\n ...state,\n timeline,\n messages: updatedMessages,\n subagents: { ...state.subagents, [event.subagentId]: subagent },\n };\n }\n\n case \"subagent_text_delta\": {\n const sa = state.subagents[event.subagentId];\n if (!sa) return { ...state, timeline };\n return {\n ...state,\n timeline,\n subagents: {\n ...state.subagents,\n [event.subagentId]: { ...sa, content: sa.content + event.delta },\n },\n };\n }\n\n case \"subagent_tool_start\": {\n const tc: AgentToolCall = {\n id: event.toolCallId,\n toolName: event.toolName,\n subagentId: event.subagentId,\n state: \"input-streaming\",\n inputBuffer: \"\",\n startedAt: timestamp,\n };\n const sa = state.subagents[event.subagentId];\n const updatedSubagents = sa\n ? {\n ...state.subagents,\n [event.subagentId]: {\n ...sa,\n toolCallIds: [...sa.toolCallIds, event.toolCallId],\n },\n }\n : state.subagents;\n return {\n ...state,\n timeline,\n subagents: updatedSubagents,\n toolCalls: { ...state.toolCalls, [event.toolCallId]: tc },\n };\n }\n\n case \"subagent_tool_end\": {\n const tc = state.toolCalls[event.toolCallId];\n if (!tc) return { ...state, timeline };\n return {\n ...state,\n timeline,\n toolCalls: {\n ...state.toolCalls,\n [event.toolCallId]: {\n ...tc,\n state: event.error ? \"output-error\" : \"output-available\",\n output: event.output,\n errorText: event.error,\n durationMs: event.durationMs,\n endedAt: timestamp,\n },\n },\n };\n }\n\n case \"subagent_end\": {\n const sa = state.subagents[event.subagentId];\n if (!sa) return { ...state, timeline };\n return {\n ...state,\n timeline,\n subagents: {\n ...state.subagents,\n [event.subagentId]: {\n ...sa,\n status: event.error ? \"error\" : \"completed\",\n error: event.error,\n durationMs: event.durationMs,\n endedAt: timestamp,\n },\n },\n };\n }\n\n case \"subagent_model_changed\": {\n if (event.subagentId) {\n const sa = state.subagents[event.subagentId];\n if (!sa) return { ...state, timeline };\n return {\n ...state,\n timeline,\n subagents: {\n ...state.subagents,\n [event.subagentId]: { ...sa, modelId: event.modelId },\n },\n };\n }\n return { ...state, timeline };\n }\n\n // ── Observational Memory ────────────────────────────────────────────────\n case \"om_observation_start\": {\n const id = event.observationId ?? `om-obs-${Date.now()}`;\n const activity: AgentOMActivity = {\n id,\n type: \"observation\",\n status: \"streaming\",\n messageId: state.messageIds[state.messageIds.length - 1],\n };\n return {\n ...state,\n timeline,\n omActivities: { ...state.omActivities, [id]: activity },\n };\n }\n\n case \"om_observation_end\": {\n const id =\n event.observationId ??\n Object.keys(state.omActivities).find(\n (k) =>\n state.omActivities[k].type === \"observation\" &&\n state.omActivities[k].status === \"streaming\"\n );\n if (!id) return { ...state, timeline };\n return {\n ...state,\n timeline,\n omActivities: {\n ...state.omActivities,\n [id]: {\n ...state.omActivities[id],\n status: \"completed\",\n text: event.text,\n durationMs: event.durationMs,\n },\n },\n };\n }\n\n case \"om_reflection_start\": {\n const id = `om-ref-${Date.now()}`;\n const activity: AgentOMActivity = {\n id,\n type: \"reflection\",\n status: \"streaming\",\n messageId: state.messageIds[state.messageIds.length - 1],\n };\n return {\n ...state,\n timeline,\n omActivities: { ...state.omActivities, [id]: activity },\n };\n }\n\n case \"om_reflection_end\": {\n const id = Object.keys(state.omActivities).find(\n (k) =>\n state.omActivities[k].type === \"reflection\" &&\n state.omActivities[k].status === \"streaming\"\n );\n if (!id) return { ...state, timeline };\n return {\n ...state,\n timeline,\n omActivities: {\n ...state.omActivities,\n [id]: {\n ...state.omActivities[id],\n status: \"completed\",\n text: event.text,\n durationMs: event.durationMs,\n },\n },\n };\n }\n\n // ── Thinking / Reasoning ────────────────────────────────────────────────\n case \"thinking_start\": {\n const thinking: AgentThinking = {\n id: event.thinkingId,\n messageId: event.messageId,\n text: \"\",\n isStreaming: true,\n };\n const existingMsg = state.messages[event.messageId];\n return {\n ...state,\n timeline,\n thinkings: { ...state.thinkings, [event.thinkingId]: thinking },\n messages: existingMsg\n ? {\n ...state.messages,\n [event.messageId]: {\n ...existingMsg,\n thinkingIds: [...existingMsg.thinkingIds, event.thinkingId],\n },\n }\n : state.messages,\n };\n }\n\n case \"thinking_delta\": {\n const existing = state.thinkings[event.thinkingId];\n if (!existing) return { ...state, timeline };\n const newText =\n event.content !== undefined\n ? event.content\n : existing.text + event.delta;\n return {\n ...state,\n timeline,\n thinkings: {\n ...state.thinkings,\n [event.thinkingId]: { ...existing, text: newText },\n },\n };\n }\n\n case \"thinking_end\": {\n const existing = state.thinkings[event.thinkingId];\n if (!existing) return { ...state, timeline };\n return {\n ...state,\n timeline,\n thinkings: {\n ...state.thinkings,\n [event.thinkingId]: {\n ...existing,\n text: event.content,\n isStreaming: false,\n },\n },\n };\n }\n\n // ── Questions + Plans ───────────────────────────────────────────────────\n case \"ask_question\": {\n const q: AgentQuestion = {\n questionId: event.questionId,\n question: event.question,\n header: event.header,\n options: event.options,\n multiple: event.multiple,\n allowCustom: event.allowCustom,\n status: \"pending\",\n };\n // Associate the question with the last message so it renders on the right message\n const lastMsgId = state.messageIds[state.messageIds.length - 1];\n const updatedMessages = lastMsgId\n ? {\n ...state.messages,\n [lastMsgId]: {\n ...state.messages[lastMsgId],\n questionId: event.questionId,\n },\n }\n : state.messages;\n return {\n ...state,\n timeline,\n pendingQuestionId: event.questionId,\n questions: { ...state.questions, [event.questionId]: q },\n messages: updatedMessages,\n };\n }\n\n case \"question_answered\": {\n const q = state.questions[event.questionId];\n if (!q) return { ...state, timeline };\n return {\n ...state,\n timeline,\n pendingQuestionId:\n state.pendingQuestionId === event.questionId\n ? undefined\n : state.pendingQuestionId,\n questions: {\n ...state.questions,\n [event.questionId]: {\n ...q,\n status: \"answered\",\n answeredWith: event.answer,\n },\n },\n };\n }\n\n case \"plan_approval_required\": {\n const p: AgentPlanApproval = {\n planId: event.planId,\n title: event.title,\n description: event.description,\n steps: event.steps,\n status: \"pending\",\n };\n // Associate the plan with the last message so it renders on the right message\n const lastMsgId = state.messageIds[state.messageIds.length - 1];\n const updatedMessages = lastMsgId\n ? {\n ...state.messages,\n [lastMsgId]: { ...state.messages[lastMsgId], planId: event.planId },\n }\n : state.messages;\n return {\n ...state,\n timeline,\n pendingPlanId: event.planId,\n planApprovals: { ...state.planApprovals, [event.planId]: p },\n messages: updatedMessages,\n };\n }\n\n case \"plan_approved\": {\n const p = state.planApprovals[event.planId];\n if (!p) return { ...state, timeline };\n return {\n ...state,\n timeline,\n pendingPlanId:\n state.pendingPlanId === event.planId\n ? undefined\n : state.pendingPlanId,\n planApprovals: {\n ...state.planApprovals,\n [event.planId]: { ...p, status: \"approved\" },\n },\n };\n }\n\n // ── Tasks ───────────────────────────────────────────────────────────────\n case \"task_updated\":\n return {\n ...state,\n timeline,\n taskList: { tasks: event.tasks, title: event.title },\n };\n\n // ── Usage ───────────────────────────────────────────────────────────────\n case \"usage_update\":\n return {\n ...state,\n timeline,\n usage: {\n inputTokens: event.inputTokens,\n outputTokens: event.outputTokens,\n totalTokens: event.totalTokens,\n cost: event.cost,\n modelId: event.modelId,\n },\n };\n\n // ── Notices ─────────────────────────────────────────────────────────────\n case \"error\": {\n const notice: AgentNotice = {\n id: nextNoticeId(),\n level: \"error\",\n message: getErrorString(event.error),\n messageId: event.messageId,\n };\n return { ...state, timeline, notices: [...state.notices, notice] };\n }\n\n case \"info\": {\n const notice: AgentNotice = {\n id: nextNoticeId(),\n level: \"info\",\n message: event.message,\n };\n return { ...state, timeline, notices: [...state.notices, notice] };\n }\n\n case \"follow_up_queued\": {\n const notice: AgentNotice = {\n id: nextNoticeId(),\n level: \"info\",\n message: `Follow-up queued: ${event.content}`,\n };\n return { ...state, timeline, notices: [...state.notices, notice] };\n }\n\n case \"workspace_error\":\n return {\n ...state,\n timeline,\n workspaceError: getErrorString(event.error),\n };\n\n case \"workspace_ready\":\n return { ...state, timeline, workspaceError: undefined };\n\n case \"workspace_status_changed\": {\n const notice: AgentNotice = {\n id: nextNoticeId(),\n level: \"info\",\n message: `Workspace: ${event.status}`,\n };\n return { ...state, timeline, notices: [...state.notices, notice] };\n }\n\n case \"mode_changed\":\n return {\n ...state,\n timeline,\n modeId: event.modeId,\n modeName: event.modeName,\n };\n\n case \"model_changed\":\n return {\n ...state,\n timeline,\n modelId: event.modelId,\n modelName: event.modelName,\n };\n\n case \"thread_changed\":\n return { ...initialState, threadId: event.threadId, timeline };\n\n case \"thread_created\":\n case \"thread_deleted\":\n case \"state_changed\":\n case \"om_status\":\n return { ...state, timeline };\n\n default:\n return { ...state, timeline };\n }\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────────────────\n\nexport interface UseAgentHarnessOptions {\n /** The harness adapter to subscribe to. Pass `null` to skip subscription. */\n adapter: HarnessAdapter | null;\n}\n\nexport interface UseAgentHarnessReturn {\n /** Full normalized harness UI state. */\n state: AgentHarnessState;\n /** Send a user message. */\n sendMessage: (params: {\n content: string;\n files?: Array<{ url: string; mediaType: string; filename: string }>;\n }) => Promise<void>;\n /** Respond to a pending tool approval. */\n respondToToolApproval: (decision: \"approve\" | \"decline\") => Promise<void>;\n /** Respond to a pending question. */\n respondToQuestion: (questionId: string, answer: string) => Promise<void>;\n /** Respond to a pending plan approval. */\n respondToPlanApproval: (\n planId: string,\n response: { action: \"approved\" | \"rejected\"; feedback?: string }\n ) => Promise<void>;\n /** Abort any in-progress generation. */\n abort: () => void;\n /** Steer the agent mid-stream. */\n steer: (content: string) => void;\n /** Select a mode. */\n selectMode: (modeId: string) => Promise<void>;\n /** Reset the state (e.g. after a thread switch). */\n reset: () => void;\n}\n\n/**\n * `useAgentHarness` — headless state hook for the AgentHarness UI.\n *\n * Subscribes to a `HarnessAdapter` and reduces all events into a single\n * normalized `AgentHarnessState` object that the `AgentHarness` block\n * (or any custom UI) can render from.\n *\n * @example\n * ```tsx\n * const adapter = fromMastraHarness(harness);\n * const { state, sendMessage, abort } = useAgentHarness({ adapter });\n * ```\n */\nexport function useAgentHarness({\n adapter,\n}: UseAgentHarnessOptions): UseAgentHarnessReturn {\n const [state, dispatch] = useReducer(agentHarnessReducer, initialState);\n\n // Keep a stable ref to the adapter so callbacks below don't stale-close\n const adapterRef = useRef<HarnessAdapter | null>(adapter);\n adapterRef.current = adapter;\n\n // Subscribe to harness events — stamp each with Date.now() for timeline\n useEffect(() => {\n if (!adapter) return;\n const unsubscribe = adapter.subscribe((event) => {\n dispatch({ type: \"EVENT\", event, timestamp: Date.now() });\n });\n return unsubscribe;\n }, [adapter]);\n\n const sendMessage = useCallback(\n async (params: {\n content: string;\n files?: Array<{ url: string; mediaType: string; filename: string }>;\n }) => {\n await adapterRef.current?.sendMessage(params);\n },\n []\n );\n\n const respondToToolApproval = useCallback(\n async (decision: \"approve\" | \"decline\") => {\n await adapterRef.current?.respondToToolApproval?.({ decision });\n },\n []\n );\n\n const respondToQuestion = useCallback(\n async (questionId: string, answer: string) => {\n await adapterRef.current?.respondToQuestion?.({ questionId, answer });\n },\n []\n );\n\n const respondToPlanApproval = useCallback(\n async (\n planId: string,\n response: { action: \"approved\" | \"rejected\"; feedback?: string }\n ) => {\n await adapterRef.current?.respondToPlanApproval?.({ planId, response });\n },\n []\n );\n\n const abort = useCallback(() => {\n adapterRef.current?.abort?.();\n }, []);\n\n const steer = useCallback((content: string) => {\n adapterRef.current?.steer?.({ content });\n }, []);\n\n const selectMode = useCallback(async (modeId: string) => {\n await adapterRef.current?.selectMode?.({ modeId });\n }, []);\n\n const reset = useCallback(() => {\n dispatch({ type: \"RESET\" });\n }, []);\n\n return {\n state,\n sendMessage,\n respondToToolApproval,\n respondToQuestion,\n respondToPlanApproval,\n abort,\n steer,\n selectMode,\n reset,\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalflare-ai/ui",
3
- "version": "0.5.0",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "description": "SignalFlare AI component library for building modern web applications",
6
6
  "keywords": [
@@ -204,10 +204,6 @@
204
204
  "types": "./dist/src/components/signalflare-ai-logo/index.d.ts",
205
205
  "import": "./dist/components/signalflare-ai-logo.js"
206
206
  },
207
- "./components/ai-loader": {
208
- "types": "./dist/src/components/ai-loader/index.d.ts",
209
- "import": "./dist/components/ai-loader.js"
210
- },
211
207
  "./components/ai-streaming-text": {
212
208
  "types": "./dist/src/components/ai-streaming-text/index.d.ts",
213
209
  "import": "./dist/components/ai-streaming-text.js"
@@ -312,6 +308,22 @@
312
308
  "types": "./dist/src/components/data-grid/index.d.ts",
313
309
  "import": "./dist/components/data-grid.js"
314
310
  },
311
+ "./components/stat-card": {
312
+ "types": "./dist/src/components/stat-card/index.d.ts",
313
+ "import": "./dist/components/stat-card.js"
314
+ },
315
+ "./components/sparkline": {
316
+ "types": "./dist/src/components/sparkline/index.d.ts",
317
+ "import": "./dist/components/sparkline.js"
318
+ },
319
+ "./components/ai-part-group": {
320
+ "types": "./dist/src/components/ai-part-group/index.d.ts",
321
+ "import": "./dist/components/ai-part-group.js"
322
+ },
323
+ "./components/text-roll": {
324
+ "types": "./dist/src/components/text-roll/index.d.ts",
325
+ "import": "./dist/components/text-roll.js"
326
+ },
315
327
  "./utils": {
316
328
  "types": "./dist/src/utils/index.d.ts",
317
329
  "import": "./dist/utils.js"
@@ -412,6 +424,10 @@
412
424
  "types": "./dist/src/primitives/number-field.d.ts",
413
425
  "import": "./dist/primitives/number-field.js"
414
426
  },
427
+ "./primitives/otp-field": {
428
+ "types": "./dist/src/primitives/otp-field.d.ts",
429
+ "import": "./dist/primitives/otp-field.js"
430
+ },
415
431
  "./primitives/popover": {
416
432
  "types": "./dist/src/primitives/popover.d.ts",
417
433
  "import": "./dist/primitives/popover.js"
@@ -496,6 +512,7 @@
496
512
  "./registry/component-registry.md": "./ai/component-registry.md",
497
513
  "./styles/tailwind": "./dist/styles/sf.css",
498
514
  "./styles/standalone": "./dist/styles/sf-standalone.css",
515
+ "./styles/shadcn": "./dist/styles/shadcn.css",
499
516
  "./styles": "./dist/styles/sf.css",
500
517
  "./styles/*": "./dist/styles/*.css",
501
518
  "./scripts/theme-generator/config": "./scripts/theme-generator/config.ts",
@@ -503,14 +520,14 @@
503
520
  },
504
521
  "publishConfig": {
505
522
  "access": "public",
506
- "registry": "https://registry.npmjs.org",
507
- "provenance": "false"
523
+ "registry": "https://registry.npmjs.org"
508
524
  },
509
525
  "scripts": {
510
526
  "prepublish": "bun run clean && bun run codegen:registry && bun run build && bun run test:unit",
511
527
  "build": "vite build --mode production && bun scripts/css-build.ts && bun src/command-line/build-cli.ts",
512
528
  "dev": "vite build --watch --mode development",
513
529
  "new:component": "plop component",
530
+ "new:story": "plop story",
514
531
  "clean": "rm -rf dist",
515
532
  "codegen": "bun run codegen:primitives && bun run codegen:themes && bun run codegen:registry",
516
533
  "codegen:themes": "bun scripts/theme-generator/index.ts",
@@ -518,7 +535,7 @@
518
535
  "codegen:primitives": "bun scripts/generate-primitives.ts",
519
536
  "codegen:registry": "bun --filter @signalflare-ai/ui-docs codegen:demos && bun scripts/component-registry/index.ts",
520
537
  "lint": "bun run lint:oxlint",
521
- "lint:oxlint": "oxlint --config .oxlintrc.json --ignore-pattern='**/*.test.*' --ignore-pattern='**/*.spec.*' --ignore-pattern='**/__tests__/**' src/** --type-aware",
538
+ "lint:oxlint": "oxlint --config ../../oxlint.config.ts --ignore-pattern='**/*.test.*' --ignore-pattern='**/*.spec.*' --ignore-pattern='**/__tests__/**' src/** --type-aware",
522
539
  "test": "CI=true vitest run --project=unit",
523
540
  "test:ui": "vitest --ui",
524
541
  "test:run": "vitest run",
@@ -526,30 +543,40 @@
526
543
  "test:coverage": "vitest run --coverage",
527
544
  "test:exports": "vitest run --project=unit tests/imports/export-path-validation.test.ts",
528
545
  "test:watch": "vitest run --project=unit --watch",
529
- "typecheck": "tsc --noEmit",
546
+ "typecheck": "tsgo --noEmit",
530
547
  "validate:build": "vitest run --project=unit tests/imports/export-path-validation.test.ts",
531
- "validate:changeset": "bun ../../ci/scripts/validate-sf-changeset.ts"
548
+ "validate:changeset": "bun ../../ci/scripts/validate-sf-changeset.ts",
549
+ "storybook": "storybook dev -p 6006",
550
+ "build-storybook": "storybook build"
532
551
  },
533
552
  "dependencies": {
534
- "@base-ui/react": "1.3.0",
535
- "@json-render/core": "^0.15.0",
536
- "@json-render/react": "^0.15.0",
553
+ "@base-ui/react": "1.4.1",
554
+ "@json-render/core": "^0.18.0",
555
+ "@json-render/react": "^0.18.0",
556
+ "@tanstack/react-store": "^0.11.0",
557
+ "@tanstack/store": "^0.11.0",
537
558
  "clsx": "^2.1.1",
538
559
  "tailwind-merge": "^3.4.0"
539
560
  },
540
561
  "devDependencies": {
562
+ "@storybook/addon-mcp": "^0.5.0",
563
+ "@storybook/addon-themes": "^10.3.5",
564
+ "@storybook/addon-vitest": "^10.3.5",
565
+ "@storybook/react-vite": "^10.3.5",
541
566
  "@streamdown/code": "^1.1.1",
542
567
  "@tailwindcss/cli": "catalog:",
543
568
  "@tailwindcss/vite": "catalog:",
544
- "@tanstack/intent": "^0.0.23",
569
+ "@tanstack/intent": "^0.0.34",
545
570
  "@tanstack/react-table": "^8.21.0",
546
- "@tanstack/react-virtual": "^3.13.22",
571
+ "@tanstack/react-virtual": "^3.13.24",
547
572
  "@testing-library/react": "16.3.2",
548
573
  "@testing-library/user-event": "14.6.1",
549
574
  "@types/leaflet": "^1.9.21",
550
575
  "@types/node": "catalog:",
551
576
  "@types/react": "catalog:",
552
577
  "@types/react-dom": "catalog:",
578
+ "@vitejs/plugin-react": "^6.0.1",
579
+ "@vitest/browser": "^4.1.5",
553
580
  "@vitest/ui": "catalog:",
554
581
  "echarts": "^6.0.0",
555
582
  "h3-js": "^4.4.0",
@@ -557,8 +584,10 @@
557
584
  "leaflet": "^1.9.4",
558
585
  "motion": "^12.38.0",
559
586
  "oxlint": "catalog:",
587
+ "playwright": "^1.52.0",
560
588
  "plop": "4.0.5",
561
589
  "react-day-picker": "^9.13.2",
590
+ "storybook": "^10.3.5",
562
591
  "streamdown": "^2.5.0",
563
592
  "sugar-high": "^1.0.0",
564
593
  "tailwindcss": "catalog:",
@@ -567,7 +596,7 @@
567
596
  "vite": "catalog:",
568
597
  "vite-plugin-dts": "catalog:",
569
598
  "vitest": "catalog:",
570
- "zod": "^3.25.67"
599
+ "zod": "^4.3.6"
571
600
  },
572
601
  "peerDependencies": {
573
602
  "@phosphor-icons/react": "^2.1.10",
@@ -576,12 +605,12 @@
576
605
  "@tanstack/react-virtual": "^3.13.22",
577
606
  "echarts": "^6.0.0",
578
607
  "motion": "^12.38.0",
579
- "react": "^18.0.0 || ^19.0.0",
608
+ "react": "^19.2.5",
580
609
  "react-day-picker": "^9.13.2",
581
- "react-dom": "^18.0.0 || ^19.0.0",
610
+ "react-dom": "^19.2.5",
582
611
  "streamdown": "^2.5.0",
583
612
  "sugar-high": "^1.0.0",
584
- "zod": "^3.25.67"
613
+ "zod": "^3.25.67 || ^4.3.6"
585
614
  },
586
615
  "peerDependenciesMeta": {
587
616
  "@streamdown/code": {
@@ -120,13 +120,13 @@ export function detectExportsFromIndex(dirPath: string): DetectedExports {
120
120
 
121
121
  for (const item of items) {
122
122
  // Check if it's a type export: "type FooProps" or "type Foo as Bar"
123
- const typeMatch = item.match(/^type\s+(\w+)(?:\s+as\s+(\w+))?/);
123
+ const typeMatch = /^type\s+(\w+)(?:\s+as\s+(\w+))?/.exec(item);
124
124
  if (typeMatch) {
125
125
  // Use aliased name if present, otherwise original name
126
126
  typeExports.push(typeMatch[2] || typeMatch[1]);
127
127
  } else {
128
128
  // Regular named export, could have "as" alias: "Foo as Bar"
129
- const nameMatch = item.match(/^(\w+)(?:\s+as\s+(\w+))?/);
129
+ const nameMatch = /^(\w+)(?:\s+as\s+(\w+))?/.exec(item);
130
130
  if (nameMatch) {
131
131
  // Use aliased name if present, otherwise original name
132
132
  namedExports.push(nameMatch[2] || nameMatch[1]);
@@ -120,7 +120,7 @@ function loadDemoExamples(): Map<string, { aiExamples: string[] }> {
120
120
  return examples;
121
121
  }
122
122
 
123
- const __dirname = dirname(fileURLToPath(import.meta.url));
123
+ const __dirname = import.meta.dirname;
124
124
  const componentsDir = join(__dirname, "../../src/components");
125
125
  const blocksDir = join(__dirname, "../../src/blocks");
126
126
  const rootDir = join(__dirname, "../..");
@@ -12,7 +12,7 @@ import * as ts from "typescript";
12
12
 
13
13
  import type { CLIFlags } from "./types.js";
14
14
 
15
- const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const __dirname = import.meta.dirname;
16
16
  const rootDir = join(__dirname, "../..");
17
17
 
18
18
  // =============================================================================
@@ -8,7 +8,7 @@ import { readFileSync } from "node:fs";
8
8
  import { join, dirname } from "node:path";
9
9
  import { fileURLToPath } from "node:url";
10
10
 
11
- const __dirname = dirname(fileURLToPath(import.meta.url));
11
+ const __dirname = import.meta.dirname;
12
12
 
13
13
  // =============================================================================
14
14
  // String Transformation Utilities
@@ -165,13 +165,13 @@ export function extractStateClasses(
165
165
  if (!cls) continue;
166
166
 
167
167
  // Check for hover states
168
- if (cls.startsWith("hover:") || cls.match(/^\[&:hover[^\]]*\]:/)) {
168
+ if (cls.startsWith("hover:") || /^\[&:hover[^\]]*\]:/.exec(cls)) {
169
169
  states.hover = states.hover ? `${states.hover} ${cls}` : cls;
170
170
  }
171
171
  // Check for focus states (focus, focus-visible, focus-within)
172
172
  else if (
173
- cls.match(/^(focus|focus-visible|focus-within):/) ||
174
- cls.match(/^\[&:focus(-visible|-within)?[^\]]*\]:/)
173
+ /^(focus|focus-visible|focus-within):/.exec(cls) ||
174
+ /^\[&:focus(-visible|-within)?[^\]]*\]:/.exec(cls)
175
175
  ) {
176
176
  states.focus = states.focus ? `${states.focus} ${cls}` : cls;
177
177
  }
@@ -235,7 +235,7 @@ export function extractBlockDependencies(sourceFile: string): string[] {
235
235
  continue;
236
236
  }
237
237
  // Extract name (handle "Foo as Bar" -> "Foo")
238
- const nameMatch = item.match(/^(\w+)(?:\s+as\s+\w+)?/);
238
+ const nameMatch = /^(\w+)(?:\s+as\s+\w+)?/.exec(item);
239
239
  if (nameMatch) {
240
240
  dependencies.add(nameMatch[1]);
241
241
  }