@flamingo-stack/openframe-frontend-core 0.0.204 → 0.0.205

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 (509) hide show
  1. package/dist/{chunk-4CWSZPXH.cjs → chunk-24KCAECR.cjs} +9 -9
  2. package/dist/{chunk-4CWSZPXH.cjs.map → chunk-24KCAECR.cjs.map} +1 -1
  3. package/dist/chunk-27APPAJN.cjs +24 -0
  4. package/dist/chunk-27APPAJN.cjs.map +1 -0
  5. package/dist/{chunk-UC43NICZ.cjs → chunk-664KA5FI.cjs} +2 -35
  6. package/dist/chunk-664KA5FI.cjs.map +1 -0
  7. package/dist/chunk-6RZYJICV.cjs +24 -0
  8. package/dist/chunk-6RZYJICV.cjs.map +1 -0
  9. package/dist/chunk-7L4DWM7P.js +24 -0
  10. package/dist/chunk-7L4DWM7P.js.map +1 -0
  11. package/dist/chunk-BZFW3FOF.cjs +21 -0
  12. package/dist/chunk-BZFW3FOF.cjs.map +1 -0
  13. package/dist/{chunk-N57KWHDB.js → chunk-CIPO6DXK.js} +5 -5
  14. package/dist/chunk-EL5YVPD5.js +21 -0
  15. package/dist/chunk-EL5YVPD5.js.map +1 -0
  16. package/dist/{chunk-ARQ4XP64.cjs → chunk-FDCFI7YT.cjs} +40080 -31492
  17. package/dist/chunk-FDCFI7YT.cjs.map +1 -0
  18. package/dist/chunk-G7UE6RKV.cjs +121 -0
  19. package/dist/chunk-G7UE6RKV.cjs.map +1 -0
  20. package/dist/{chunk-25LVV26X.cjs → chunk-JUZGUQMX.cjs} +178 -50
  21. package/dist/chunk-JUZGUQMX.cjs.map +1 -0
  22. package/dist/{chunk-SZPJ5R5B.js → chunk-KSOOKNBG.js} +1 -34
  23. package/dist/chunk-KSOOKNBG.js.map +1 -0
  24. package/dist/{chunk-RMB5DVED.cjs → chunk-KUZGEA7U.cjs} +83 -66
  25. package/dist/chunk-KUZGEA7U.cjs.map +1 -0
  26. package/dist/chunk-LXC6P2EO.js +63 -0
  27. package/dist/chunk-LXC6P2EO.js.map +1 -0
  28. package/dist/chunk-MJNXIEV2.js +24 -0
  29. package/dist/chunk-MJNXIEV2.js.map +1 -0
  30. package/dist/{chunk-CPXLQ57U.js → chunk-MVGGXOFA.js} +37 -20
  31. package/dist/chunk-MVGGXOFA.js.map +1 -0
  32. package/dist/{chunk-LY34ORX6.js → chunk-O55ZUAX7.js} +39920 -31332
  33. package/dist/chunk-O55ZUAX7.js.map +1 -0
  34. package/dist/chunk-OHPI2HRK.js +47 -0
  35. package/dist/chunk-OHPI2HRK.js.map +1 -0
  36. package/dist/chunk-PLJLE4A4.js +121 -0
  37. package/dist/chunk-PLJLE4A4.js.map +1 -0
  38. package/dist/{chunk-XGL5FKIK.js → chunk-SCN5WFIZ.js} +148 -20
  39. package/dist/chunk-SCN5WFIZ.js.map +1 -0
  40. package/dist/chunk-WBR7H6E3.cjs +47 -0
  41. package/dist/chunk-WBR7H6E3.cjs.map +1 -0
  42. package/dist/chunk-XL4V2PYG.cjs +63 -0
  43. package/dist/chunk-XL4V2PYG.cjs.map +1 -0
  44. package/dist/components/announcement-bar.d.ts.map +1 -1
  45. package/dist/components/chat/chat-attachment-bar.d.ts +66 -0
  46. package/dist/components/chat/chat-attachment-bar.d.ts.map +1 -0
  47. package/dist/components/chat/chat-container.d.ts +21 -1
  48. package/dist/components/chat/chat-container.d.ts.map +1 -1
  49. package/dist/components/chat/chat-input.d.ts.map +1 -1
  50. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  51. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  52. package/dist/components/chat/chat-panel-context.d.ts +9 -0
  53. package/dist/components/chat/chat-panel-context.d.ts.map +1 -0
  54. package/dist/components/chat/chat-ticket-list.d.ts +1 -1
  55. package/dist/components/chat/chat-ticket-list.d.ts.map +1 -1
  56. package/dist/components/chat/embeddable-chat.d.ts +42 -0
  57. package/dist/components/chat/embeddable-chat.d.ts.map +1 -0
  58. package/dist/components/chat/entity-cards/admin-content-card.d.ts +34 -0
  59. package/dist/components/chat/entity-cards/admin-content-card.d.ts.map +1 -0
  60. package/dist/components/chat/entity-cards/block-card.d.ts.map +1 -0
  61. package/dist/components/chat/entity-cards/blog-card.d.ts +30 -0
  62. package/dist/components/chat/entity-cards/blog-card.d.ts.map +1 -0
  63. package/dist/components/chat/entity-cards/blog-image-placeholder.d.ts +26 -0
  64. package/dist/components/chat/entity-cards/blog-image-placeholder.d.ts.map +1 -0
  65. package/dist/components/chat/entity-cards/campaign-card-admin.d.ts +33 -0
  66. package/dist/components/chat/entity-cards/campaign-card-admin.d.ts.map +1 -0
  67. package/dist/components/chat/entity-cards/case-study-card.d.ts +20 -0
  68. package/dist/components/chat/entity-cards/case-study-card.d.ts.map +1 -0
  69. package/dist/components/chat/entity-cards/chat-ticket-item.d.ts.map +1 -0
  70. package/dist/components/chat/{chat-video-entity-card.d.ts → entity-cards/chat-video-entity-card.d.ts} +1 -1
  71. package/dist/components/chat/entity-cards/chat-video-entity-card.d.ts.map +1 -0
  72. package/dist/components/chat/entity-cards/customer-interview-card.d.ts +19 -0
  73. package/dist/components/chat/entity-cards/customer-interview-card.d.ts.map +1 -0
  74. package/dist/components/chat/entity-cards/data-room-doc-card.d.ts +47 -0
  75. package/dist/components/chat/entity-cards/data-room-doc-card.d.ts.map +1 -0
  76. package/dist/components/chat/entity-cards/dispatch.d.ts +119 -0
  77. package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -0
  78. package/dist/components/chat/entity-cards/entity-author-card.d.ts +87 -0
  79. package/dist/components/chat/entity-cards/entity-author-card.d.ts.map +1 -0
  80. package/dist/components/chat/entity-cards/generic-entity-card.d.ts +42 -0
  81. package/dist/components/chat/entity-cards/generic-entity-card.d.ts.map +1 -0
  82. package/dist/components/chat/entity-cards/github-activity-card.d.ts +37 -0
  83. package/dist/components/chat/entity-cards/github-activity-card.d.ts.map +1 -0
  84. package/dist/components/chat/entity-cards/hubspot-ticket-card.d.ts +28 -0
  85. package/dist/components/chat/entity-cards/hubspot-ticket-card.d.ts.map +1 -0
  86. package/dist/components/chat/entity-cards/index.d.ts +32 -0
  87. package/dist/components/chat/entity-cards/index.d.ts.map +1 -0
  88. package/dist/components/chat/entity-cards/investor-update-card.d.ts +19 -0
  89. package/dist/components/chat/entity-cards/investor-update-card.d.ts.map +1 -0
  90. package/dist/components/chat/entity-cards/onboarding-guide-card.d.ts +20 -0
  91. package/dist/components/chat/entity-cards/onboarding-guide-card.d.ts.map +1 -0
  92. package/dist/components/chat/entity-cards/product-release-card-defaults.d.ts +21 -0
  93. package/dist/components/chat/entity-cards/product-release-card-defaults.d.ts.map +1 -0
  94. package/dist/components/chat/entity-cards/product-release-card.d.ts +12 -0
  95. package/dist/components/chat/entity-cards/product-release-card.d.ts.map +1 -0
  96. package/dist/components/chat/entity-cards/program-card-defaults.d.ts +32 -0
  97. package/dist/components/chat/entity-cards/program-card-defaults.d.ts.map +1 -0
  98. package/dist/components/chat/entity-cards/program-card.d.ts +37 -0
  99. package/dist/components/chat/entity-cards/program-card.d.ts.map +1 -0
  100. package/dist/components/chat/entity-cards/roadmap-card.d.ts +28 -0
  101. package/dist/components/chat/entity-cards/roadmap-card.d.ts.map +1 -0
  102. package/dist/components/chat/entity-cards/roadmap-vote-button.d.ts +12 -0
  103. package/dist/components/chat/entity-cards/roadmap-vote-button.d.ts.map +1 -0
  104. package/dist/components/chat/entity-cards/slack-message-card.d.ts +28 -0
  105. package/dist/components/chat/entity-cards/slack-message-card.d.ts.map +1 -0
  106. package/dist/components/chat/entity-cards/task-type-icon.d.ts +6 -0
  107. package/dist/components/chat/entity-cards/task-type-icon.d.ts.map +1 -0
  108. package/dist/components/chat/hooks/index.d.ts +10 -0
  109. package/dist/components/chat/hooks/index.d.ts.map +1 -1
  110. package/dist/components/chat/hooks/use-chat-attachment-image-gallery.d.ts +5 -0
  111. package/dist/components/chat/hooks/use-chat-attachment-image-gallery.d.ts.map +1 -0
  112. package/dist/components/chat/hooks/use-chat-attachments.d.ts +33 -0
  113. package/dist/components/chat/hooks/use-chat-attachments.d.ts.map +1 -0
  114. package/dist/components/chat/hooks/use-chat-card-item.d.ts +7 -0
  115. package/dist/components/chat/hooks/use-chat-card-item.d.ts.map +1 -0
  116. package/dist/components/chat/hooks/use-chat-identity.d.ts +44 -0
  117. package/dist/components/chat/hooks/use-chat-identity.d.ts.map +1 -0
  118. package/dist/components/chat/hooks/use-chat.d.ts +30 -0
  119. package/dist/components/chat/hooks/use-chat.d.ts.map +1 -0
  120. package/dist/components/chat/hooks/use-close-on-navigation.d.ts +2 -0
  121. package/dist/components/chat/hooks/use-close-on-navigation.d.ts.map +1 -0
  122. package/dist/components/chat/hooks/use-embedded-chat.d.ts +174 -0
  123. package/dist/components/chat/hooks/use-embedded-chat.d.ts.map +1 -0
  124. package/dist/components/chat/hooks/use-proxied-image-url.d.ts +18 -0
  125. package/dist/components/chat/hooks/use-proxied-image-url.d.ts.map +1 -0
  126. package/dist/components/chat/hooks/use-slash-commands.d.ts +32 -0
  127. package/dist/components/chat/hooks/use-slash-commands.d.ts.map +1 -0
  128. package/dist/components/chat/hooks/use-sse.d.ts +57 -0
  129. package/dist/components/chat/hooks/use-sse.d.ts.map +1 -0
  130. package/dist/components/chat/index.cjs +393 -0
  131. package/dist/components/chat/index.cjs.map +1 -0
  132. package/dist/components/chat/index.d.ts +5 -3
  133. package/dist/components/chat/index.d.ts.map +1 -1
  134. package/dist/components/chat/index.js +393 -0
  135. package/dist/components/chat/index.js.map +1 -0
  136. package/dist/components/chat/nav-link-anchor-via-runtime.d.ts +33 -0
  137. package/dist/components/chat/nav-link-anchor-via-runtime.d.ts.map +1 -0
  138. package/dist/components/chat/source-action-button.d.ts +39 -0
  139. package/dist/components/chat/source-action-button.d.ts.map +1 -0
  140. package/dist/components/chat/types/chat.types.d.ts +36 -0
  141. package/dist/components/chat/types/chat.types.d.ts.map +1 -1
  142. package/dist/components/chat/types/component.types.d.ts +56 -11
  143. package/dist/components/chat/types/component.types.d.ts.map +1 -1
  144. package/dist/components/chat/types/entities/blog.d.ts +14 -0
  145. package/dist/components/chat/types/entities/blog.d.ts.map +1 -0
  146. package/dist/components/chat/types/entities/case-study.d.ts +10 -0
  147. package/dist/components/chat/types/entities/case-study.d.ts.map +1 -0
  148. package/dist/components/chat/types/entities/content-ref.d.ts +23 -0
  149. package/dist/components/chat/types/entities/content-ref.d.ts.map +1 -0
  150. package/dist/components/chat/types/entities/customer-interview.d.ts +10 -0
  151. package/dist/components/chat/types/entities/customer-interview.d.ts.map +1 -0
  152. package/dist/components/chat/types/entities/data-room-doc.d.ts +37 -0
  153. package/dist/components/chat/types/entities/data-room-doc.d.ts.map +1 -0
  154. package/dist/components/chat/types/entities/github-activity.d.ts +29 -0
  155. package/dist/components/chat/types/entities/github-activity.d.ts.map +1 -0
  156. package/dist/components/chat/types/entities/hubspot-ticket.d.ts +39 -0
  157. package/dist/components/chat/types/entities/hubspot-ticket.d.ts.map +1 -0
  158. package/dist/components/chat/types/entities/index.d.ts +28 -0
  159. package/dist/components/chat/types/entities/index.d.ts.map +1 -0
  160. package/dist/components/chat/types/entities/investor-update.d.ts +83 -0
  161. package/dist/components/chat/types/entities/investor-update.d.ts.map +1 -0
  162. package/dist/components/chat/types/entities/onboarding-guide.d.ts +79 -0
  163. package/dist/components/chat/types/entities/onboarding-guide.d.ts.map +1 -0
  164. package/dist/components/chat/types/entities/program-types.d.ts +303 -0
  165. package/dist/components/chat/types/entities/program-types.d.ts.map +1 -0
  166. package/dist/components/chat/types/entities/roadmap-item.d.ts +41 -0
  167. package/dist/components/chat/types/entities/roadmap-item.d.ts.map +1 -0
  168. package/dist/components/chat/types/entities/slack-message.d.ts +28 -0
  169. package/dist/components/chat/types/entities/slack-message.d.ts.map +1 -0
  170. package/dist/components/chat/types/index.d.ts +1 -0
  171. package/dist/components/chat/types/index.d.ts.map +1 -1
  172. package/dist/components/chat/utils/agent-status-message.d.ts +18 -0
  173. package/dist/components/chat/utils/agent-status-message.d.ts.map +1 -0
  174. package/dist/components/chat/utils/auto-continuation-directive.d.ts +38 -0
  175. package/dist/components/chat/utils/auto-continuation-directive.d.ts.map +1 -0
  176. package/dist/components/chat/utils/chat-attachment-markdown.d.ts +114 -0
  177. package/dist/components/chat/utils/chat-attachment-markdown.d.ts.map +1 -0
  178. package/dist/components/chat/utils/chat-authed-fetch.d.ts +13 -0
  179. package/dist/components/chat/utils/chat-authed-fetch.d.ts.map +1 -0
  180. package/dist/components/chat/utils/chat-nav-resolution.d.ts +72 -0
  181. package/dist/components/chat/utils/chat-nav-resolution.d.ts.map +1 -0
  182. package/dist/components/chat/utils/chat-proxy-auth-storage.d.ts +43 -0
  183. package/dist/components/chat/utils/chat-proxy-auth-storage.d.ts.map +1 -0
  184. package/dist/components/chat/utils/chip-action-class.d.ts +16 -0
  185. package/dist/components/chat/utils/chip-action-class.d.ts.map +1 -0
  186. package/dist/components/chat/utils/chip-styles.d.ts +32 -0
  187. package/dist/components/chat/utils/chip-styles.d.ts.map +1 -0
  188. package/dist/components/chat/utils/clickup-task-type-utils.d.ts +38 -0
  189. package/dist/components/chat/utils/clickup-task-type-utils.d.ts.map +1 -0
  190. package/dist/components/chat/utils/compact-card-classes.d.ts +50 -0
  191. package/dist/components/chat/utils/compact-card-classes.d.ts.map +1 -0
  192. package/dist/components/chat/utils/decide-new-tab.d.ts +39 -0
  193. package/dist/components/chat/utils/decide-new-tab.d.ts.map +1 -0
  194. package/dist/components/chat/utils/external-app-urls.d.ts +14 -0
  195. package/dist/components/chat/utils/external-app-urls.d.ts.map +1 -0
  196. package/dist/components/chat/utils/flatten-assistant-content.d.ts +25 -0
  197. package/dist/components/chat/utils/flatten-assistant-content.d.ts.map +1 -0
  198. package/dist/components/chat/utils/icon-registry.d.ts +67 -0
  199. package/dist/components/chat/utils/icon-registry.d.ts.map +1 -0
  200. package/dist/components/chat/utils/index.d.ts +21 -0
  201. package/dist/components/chat/utils/index.d.ts.map +1 -1
  202. package/dist/components/chat/utils/is-cross-origin-url.d.ts +22 -0
  203. package/dist/components/chat/utils/is-cross-origin-url.d.ts.map +1 -0
  204. package/dist/components/chat/utils/nav-anchor-props.d.ts +54 -0
  205. package/dist/components/chat/utils/nav-anchor-props.d.ts.map +1 -0
  206. package/dist/components/chat/utils/nav-click-handler.d.ts +51 -0
  207. package/dist/components/chat/utils/nav-click-handler.d.ts.map +1 -0
  208. package/dist/components/chat/utils/scroll-anchor.d.ts +30 -0
  209. package/dist/components/chat/utils/scroll-anchor.d.ts.map +1 -0
  210. package/dist/components/chat/utils/slash-dispatch-utils.d.ts +109 -0
  211. package/dist/components/chat/utils/slash-dispatch-utils.d.ts.map +1 -0
  212. package/dist/components/chat/utils/source-icons.d.ts +8 -0
  213. package/dist/components/chat/utils/source-icons.d.ts.map +1 -0
  214. package/dist/components/chat/utils/source-row-cta.d.ts +111 -0
  215. package/dist/components/chat/utils/source-row-cta.d.ts.map +1 -0
  216. package/dist/components/features/figma-prototype-viewer.d.ts.map +1 -1
  217. package/dist/components/features/index.cjs +12 -6
  218. package/dist/components/features/index.cjs.map +1 -1
  219. package/dist/components/features/index.js +11 -5
  220. package/dist/components/features/video.d.ts.map +1 -1
  221. package/dist/components/icons/index.cjs +3 -3
  222. package/dist/components/icons/index.js +2 -2
  223. package/dist/components/index.cjs +274 -8
  224. package/dist/components/index.cjs.map +1 -1
  225. package/dist/components/index.js +273 -7
  226. package/dist/components/interactive-wrapper.d.ts +3 -3
  227. package/dist/components/navigation/index.cjs +12 -6
  228. package/dist/components/navigation/index.cjs.map +1 -1
  229. package/dist/components/navigation/index.js +11 -5
  230. package/dist/components/resizable.d.ts +1 -1
  231. package/dist/components/shared/product-release/product-release-card-skeleton.d.ts +1 -1
  232. package/dist/components/shared/product-release/product-release-card-skeleton.d.ts.map +1 -1
  233. package/dist/components/shared/product-release/product-release-card.d.ts +19 -12
  234. package/dist/components/shared/product-release/product-release-card.d.ts.map +1 -1
  235. package/dist/components/shared/product-release/release-detail-page.d.ts +2 -4
  236. package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
  237. package/dist/components/ui/button/button.d.ts +13 -0
  238. package/dist/components/ui/button/button.d.ts.map +1 -1
  239. package/dist/components/ui/dashboard-info-card.d.ts.map +1 -1
  240. package/dist/components/ui/entity-image.d.ts.map +1 -1
  241. package/dist/components/ui/file-manager/index.cjs +71 -70
  242. package/dist/components/ui/file-manager/index.cjs.map +1 -1
  243. package/dist/components/ui/file-manager/index.js +6 -5
  244. package/dist/components/ui/file-manager/index.js.map +1 -1
  245. package/dist/components/ui/hover-dropdown.d.ts +66 -0
  246. package/dist/components/ui/hover-dropdown.d.ts.map +1 -0
  247. package/dist/components/ui/index.cjs +276 -6
  248. package/dist/components/ui/index.cjs.map +1 -1
  249. package/dist/components/ui/index.d.ts +1 -0
  250. package/dist/components/ui/index.d.ts.map +1 -1
  251. package/dist/components/ui/index.js +278 -8
  252. package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
  253. package/dist/components/ui/square-avatar.d.ts.map +1 -1
  254. package/dist/contexts/chat-runtime-context.d.ts +109 -0
  255. package/dist/contexts/chat-runtime-context.d.ts.map +1 -0
  256. package/dist/contexts/endpoints-runtime-context.d.ts +28 -0
  257. package/dist/contexts/endpoints-runtime-context.d.ts.map +1 -0
  258. package/dist/contexts/index.cjs +30 -0
  259. package/dist/contexts/index.cjs.map +1 -0
  260. package/dist/contexts/index.d.ts +26 -0
  261. package/dist/contexts/index.d.ts.map +1 -0
  262. package/dist/contexts/index.js +30 -0
  263. package/dist/contexts/index.js.map +1 -0
  264. package/dist/contexts/use-outer-or-default.d.ts +29 -0
  265. package/dist/contexts/use-outer-or-default.d.ts.map +1 -0
  266. package/dist/embed-shims/index.cjs +51 -0
  267. package/dist/embed-shims/index.cjs.map +1 -0
  268. package/dist/embed-shims/index.d.ts +31 -0
  269. package/dist/embed-shims/index.d.ts.map +1 -0
  270. package/dist/embed-shims/index.js +51 -0
  271. package/dist/embed-shims/index.js.map +1 -0
  272. package/dist/embed-shims/next-dynamic.cjs +12 -0
  273. package/dist/embed-shims/next-dynamic.cjs.map +1 -0
  274. package/dist/embed-shims/next-dynamic.d.ts +47 -0
  275. package/dist/embed-shims/next-dynamic.d.ts.map +1 -0
  276. package/dist/embed-shims/next-dynamic.js +12 -0
  277. package/dist/embed-shims/next-dynamic.js.map +1 -0
  278. package/dist/embed-shims/next-image.cjs +12 -0
  279. package/dist/embed-shims/next-image.cjs.map +1 -0
  280. package/dist/embed-shims/next-image.d.ts +28 -0
  281. package/dist/embed-shims/next-image.d.ts.map +1 -0
  282. package/dist/embed-shims/next-image.js +12 -0
  283. package/dist/embed-shims/next-image.js.map +1 -0
  284. package/dist/embed-shims/next-link.cjs +14 -0
  285. package/dist/embed-shims/next-link.cjs.map +1 -0
  286. package/dist/embed-shims/next-link.d.ts +22 -0
  287. package/dist/embed-shims/next-link.d.ts.map +1 -0
  288. package/dist/embed-shims/next-link.js +14 -0
  289. package/dist/embed-shims/next-link.js.map +1 -0
  290. package/dist/embed-shims/next-navigation.cjs +30 -0
  291. package/dist/embed-shims/next-navigation.cjs.map +1 -0
  292. package/dist/embed-shims/next-navigation.d.ts +46 -0
  293. package/dist/embed-shims/next-navigation.d.ts.map +1 -0
  294. package/dist/embed-shims/next-navigation.js +30 -0
  295. package/dist/embed-shims/next-navigation.js.map +1 -0
  296. package/dist/hooks/index.cjs +10 -4
  297. package/dist/hooks/index.cjs.map +1 -1
  298. package/dist/hooks/index.d.ts +2 -0
  299. package/dist/hooks/index.d.ts.map +1 -1
  300. package/dist/hooks/index.js +9 -3
  301. package/dist/hooks/use-access-code-integration.d.ts +48 -0
  302. package/dist/hooks/use-access-code-integration.d.ts.map +1 -0
  303. package/dist/hooks/use-contact-submission.d.ts.map +1 -1
  304. package/dist/hooks/use-og-placeholder.d.ts +31 -0
  305. package/dist/hooks/use-og-placeholder.d.ts.map +1 -0
  306. package/dist/hooks/use-toast.d.ts +1 -1
  307. package/dist/index.cjs +367 -7
  308. package/dist/index.cjs.map +1 -1
  309. package/dist/index.js +378 -18
  310. package/dist/types/index.cjs.map +1 -1
  311. package/dist/types/index.js.map +1 -1
  312. package/dist/utils/access-code-client.d.ts +21 -37
  313. package/dist/utils/access-code-client.d.ts.map +1 -1
  314. package/dist/utils/cn.d.ts +0 -27
  315. package/dist/utils/cn.d.ts.map +1 -1
  316. package/dist/utils/color-analysis.d.ts +33 -0
  317. package/dist/utils/color-analysis.d.ts.map +1 -0
  318. package/dist/utils/date-formatters.d.ts +16 -5
  319. package/dist/utils/date-formatters.d.ts.map +1 -1
  320. package/dist/utils/fetch-priority.d.ts +3 -0
  321. package/dist/utils/fetch-priority.d.ts.map +1 -0
  322. package/dist/utils/format.d.ts +192 -1
  323. package/dist/utils/format.d.ts.map +1 -1
  324. package/dist/utils/image-proxy.d.ts +67 -2
  325. package/dist/utils/image-proxy.d.ts.map +1 -1
  326. package/dist/utils/index.cjs +1274 -155
  327. package/dist/utils/index.cjs.map +1 -1
  328. package/dist/utils/index.d.ts +19 -3
  329. package/dist/utils/index.d.ts.map +1 -1
  330. package/dist/utils/index.js +1200 -157
  331. package/dist/utils/index.js.map +1 -1
  332. package/dist/utils/local-storage-adapter.d.ts +46 -0
  333. package/dist/utils/local-storage-adapter.d.ts.map +1 -0
  334. package/dist/utils/source-icons.d.ts +78 -0
  335. package/dist/utils/source-icons.d.ts.map +1 -0
  336. package/package.json +29 -2
  337. package/src/components/announcement-bar.tsx +26 -4
  338. package/src/components/categories-cart.tsx +1 -1
  339. package/src/components/chat/chat-attachment-bar.tsx +323 -0
  340. package/src/components/chat/chat-container.tsx +39 -5
  341. package/src/components/chat/chat-input.tsx +7 -1
  342. package/src/components/chat/chat-message-enhanced.tsx +32 -22
  343. package/src/components/chat/chat-message-list.tsx +53 -4
  344. package/src/components/chat/chat-panel-context.tsx +37 -0
  345. package/src/components/chat/chat-ticket-list.tsx +1 -1
  346. package/src/components/chat/embeddable-chat.tsx +1106 -0
  347. package/src/components/chat/entity-cards/admin-content-card.tsx +155 -0
  348. package/src/components/chat/entity-cards/blog-card.tsx +259 -0
  349. package/src/components/chat/entity-cards/blog-image-placeholder.tsx +52 -0
  350. package/src/components/chat/entity-cards/campaign-card-admin.tsx +113 -0
  351. package/src/components/chat/entity-cards/case-study-card.tsx +192 -0
  352. package/src/components/chat/{chat-ticket-item.tsx → entity-cards/chat-ticket-item.tsx} +2 -2
  353. package/src/components/chat/{chat-video-entity-card.tsx → entity-cards/chat-video-entity-card.tsx} +2 -2
  354. package/src/components/chat/entity-cards/customer-interview-card.tsx +211 -0
  355. package/src/components/chat/entity-cards/data-room-doc-card.tsx +120 -0
  356. package/src/components/chat/entity-cards/dispatch.tsx +1093 -0
  357. package/src/components/chat/entity-cards/entity-author-card.tsx +193 -0
  358. package/src/components/chat/entity-cards/generic-entity-card.tsx +144 -0
  359. package/src/components/chat/entity-cards/github-activity-card.tsx +305 -0
  360. package/src/components/chat/entity-cards/hubspot-ticket-card.tsx +205 -0
  361. package/src/components/chat/entity-cards/index.ts +125 -0
  362. package/src/components/chat/entity-cards/investor-update-card.tsx +150 -0
  363. package/src/components/chat/entity-cards/onboarding-guide-card.tsx +326 -0
  364. package/src/components/chat/entity-cards/product-release-card-defaults.ts +57 -0
  365. package/src/components/chat/entity-cards/product-release-card.tsx +19 -0
  366. package/src/components/chat/entity-cards/program-card-defaults.ts +62 -0
  367. package/src/components/chat/entity-cards/program-card.tsx +451 -0
  368. package/src/components/chat/entity-cards/roadmap-card.tsx +356 -0
  369. package/src/components/chat/entity-cards/roadmap-vote-button.tsx +54 -0
  370. package/src/components/chat/entity-cards/slack-message-card.tsx +182 -0
  371. package/src/components/chat/entity-cards/task-type-icon.tsx +60 -0
  372. package/src/components/chat/hooks/index.ts +22 -0
  373. package/src/components/chat/hooks/use-chat-attachment-image-gallery.tsx +114 -0
  374. package/src/components/chat/hooks/use-chat-attachments.ts +429 -0
  375. package/src/components/chat/hooks/use-chat-card-item.ts +102 -0
  376. package/src/components/chat/hooks/use-chat-identity.ts +139 -0
  377. package/src/components/chat/hooks/use-chat.ts +501 -0
  378. package/src/components/chat/hooks/use-close-on-navigation.ts +87 -0
  379. package/src/components/chat/hooks/use-embedded-chat.ts +1023 -0
  380. package/src/components/chat/hooks/use-proxied-image-url.ts +31 -0
  381. package/src/components/chat/hooks/use-slash-commands.ts +106 -0
  382. package/src/components/chat/hooks/use-sse.ts +143 -0
  383. package/src/components/chat/index.ts +30 -4
  384. package/src/components/chat/nav-link-anchor-via-runtime.tsx +72 -0
  385. package/src/components/chat/source-action-button.tsx +120 -0
  386. package/src/components/chat/types/chat.types.ts +61 -0
  387. package/src/components/chat/types/component.types.ts +57 -11
  388. package/src/components/chat/types/entities/blog.ts +27 -0
  389. package/src/components/chat/types/entities/case-study.ts +14 -0
  390. package/src/components/chat/types/entities/content-ref.ts +23 -0
  391. package/src/components/chat/types/entities/customer-interview.ts +15 -0
  392. package/src/components/chat/types/entities/data-room-doc.ts +37 -0
  393. package/src/components/chat/types/entities/github-activity.ts +36 -0
  394. package/src/components/chat/types/entities/hubspot-ticket.ts +39 -0
  395. package/src/components/chat/types/entities/index.ts +28 -0
  396. package/src/components/chat/types/entities/investor-update.ts +100 -0
  397. package/src/components/chat/types/entities/onboarding-guide.ts +101 -0
  398. package/src/components/chat/types/entities/program-types.ts +433 -0
  399. package/src/components/chat/types/entities/roadmap-item.ts +42 -0
  400. package/src/components/chat/types/entities/slack-message.ts +28 -0
  401. package/src/components/chat/types/index.ts +1 -0
  402. package/src/components/chat/utils/agent-status-message.ts +52 -0
  403. package/src/components/chat/utils/auto-continuation-directive.ts +70 -0
  404. package/src/components/chat/utils/chat-attachment-markdown.ts +190 -0
  405. package/src/components/chat/utils/chat-authed-fetch.ts +73 -0
  406. package/src/components/chat/utils/chat-nav-resolution.ts +151 -0
  407. package/src/components/chat/utils/chat-proxy-auth-storage.ts +148 -0
  408. package/src/components/chat/utils/chip-action-class.ts +19 -0
  409. package/src/components/chat/utils/chip-styles.ts +51 -0
  410. package/src/components/chat/utils/clickup-task-type-utils.ts +59 -0
  411. package/src/components/chat/utils/compact-card-classes.ts +97 -0
  412. package/src/components/chat/utils/decide-new-tab.ts +57 -0
  413. package/src/components/chat/utils/external-app-urls.ts +19 -0
  414. package/src/components/chat/utils/flatten-assistant-content.ts +35 -0
  415. package/src/components/chat/utils/icon-registry.ts +297 -0
  416. package/src/components/chat/utils/index.ts +133 -0
  417. package/src/components/chat/utils/is-cross-origin-url.ts +28 -0
  418. package/src/components/chat/utils/nav-anchor-props.ts +78 -0
  419. package/src/components/chat/utils/nav-click-handler.ts +81 -0
  420. package/src/components/chat/utils/scroll-anchor.ts +35 -0
  421. package/src/components/chat/utils/slash-dispatch-utils.ts +183 -0
  422. package/src/components/chat/utils/source-icons.ts +14 -0
  423. package/src/components/chat/utils/source-row-cta.ts +215 -0
  424. package/src/components/empty-state.tsx +1 -1
  425. package/src/components/features/board/ticket-card.tsx +1 -1
  426. package/src/components/features/figma-prototype-viewer.tsx +2 -1
  427. package/src/components/features/media-gallery-manager.tsx +1 -1
  428. package/src/components/features/parallax-image-showcase.tsx +1 -1
  429. package/src/components/features/release-media-manager.tsx +1 -1
  430. package/src/components/features/seo-editor-preview.tsx +1 -1
  431. package/src/components/features/video.tsx +54 -3
  432. package/src/components/footer-waitlist-button.tsx +1 -1
  433. package/src/components/navigation/header.tsx +1 -1
  434. package/src/components/shared/onboarding/onboarding-step-card.tsx +1 -1
  435. package/src/components/shared/product-release/product-release-card-skeleton.tsx +8 -44
  436. package/src/components/shared/product-release/product-release-card.tsx +31 -116
  437. package/src/components/shared/product-release/release-detail-page.tsx +12 -16
  438. package/src/components/ui/actions-menu.tsx +1 -1
  439. package/src/components/ui/button/button.tsx +41 -11
  440. package/src/components/ui/button/split-button.tsx +1 -1
  441. package/src/components/ui/dashboard-info-card.tsx +2 -3
  442. package/src/components/ui/data-table/data-table-row.tsx +1 -1
  443. package/src/components/ui/entity-image.tsx +2 -8
  444. package/src/components/ui/hover-dropdown.tsx +258 -0
  445. package/src/components/ui/image-gallery-modal.tsx +1 -1
  446. package/src/components/ui/index.ts +1 -0
  447. package/src/components/ui/markdown-editor.tsx +1 -1
  448. package/src/components/ui/more-actions-menu.tsx +1 -1
  449. package/src/components/ui/organization-card.tsx +1 -1
  450. package/src/components/ui/simple-markdown-renderer.tsx +53 -5
  451. package/src/components/ui/square-avatar.tsx +3 -12
  452. package/src/components/ui/tab-navigation.tsx +1 -1
  453. package/src/components/ui/table/table-row.tsx +1 -1
  454. package/src/components/unified-filter-logic.tsx +1 -1
  455. package/src/components/unified-pagination.tsx +1 -1
  456. package/src/components/user-summary-stub.tsx +1 -1
  457. package/src/components/vendor-display-button.tsx +1 -1
  458. package/src/components/vendor-icon.tsx +1 -1
  459. package/src/contexts/chat-runtime-context.tsx +163 -0
  460. package/src/contexts/endpoints-runtime-context.tsx +68 -0
  461. package/src/contexts/index.ts +38 -0
  462. package/src/contexts/use-outer-or-default.ts +42 -0
  463. package/src/embed-shims/index.ts +42 -0
  464. package/src/embed-shims/next-dynamic.tsx +70 -0
  465. package/src/embed-shims/next-image.tsx +114 -0
  466. package/src/embed-shims/next-link.tsx +91 -0
  467. package/src/embed-shims/next-navigation.tsx +201 -0
  468. package/src/hooks/index.ts +9 -0
  469. package/src/hooks/state/use-api-params.ts +1 -1
  470. package/src/hooks/state/use-query-params.ts +1 -1
  471. package/src/hooks/use-access-code-integration.ts +107 -0
  472. package/src/hooks/use-contact-submission.ts +7 -3
  473. package/src/hooks/use-og-placeholder.ts +45 -0
  474. package/src/stories/OnboardingStepCard.stories.tsx +140 -0
  475. package/src/styles/chat-animations.css +65 -0
  476. package/src/styles/index.css +1 -0
  477. package/src/utils/access-code-client.ts +32 -75
  478. package/src/utils/cn.ts +0 -65
  479. package/src/utils/color-analysis.ts +205 -0
  480. package/src/utils/date-formatters.ts +54 -11
  481. package/src/utils/fetch-priority.ts +41 -0
  482. package/src/utils/format.ts +525 -1
  483. package/src/utils/image-proxy.ts +127 -7
  484. package/src/utils/index.ts +145 -5
  485. package/src/utils/local-storage-adapter.ts +105 -0
  486. package/src/utils/source-icons.ts +219 -0
  487. package/dist/chunk-25LVV26X.cjs.map +0 -1
  488. package/dist/chunk-ARQ4XP64.cjs.map +0 -1
  489. package/dist/chunk-CPXLQ57U.js.map +0 -1
  490. package/dist/chunk-LY34ORX6.js.map +0 -1
  491. package/dist/chunk-RMB5DVED.cjs.map +0 -1
  492. package/dist/chunk-SZPJ5R5B.js.map +0 -1
  493. package/dist/chunk-UC43NICZ.cjs.map +0 -1
  494. package/dist/chunk-XGL5FKIK.js.map +0 -1
  495. package/dist/components/chat/block-card.d.ts.map +0 -1
  496. package/dist/components/chat/chat-ticket-item.d.ts.map +0 -1
  497. package/dist/components/chat/chat-video-entity-card.d.ts.map +0 -1
  498. package/dist/utils/dynamic-icons.d.ts +0 -26
  499. package/dist/utils/dynamic-icons.d.ts.map +0 -1
  500. package/dist/utils/format-relative-time.d.ts +0 -21
  501. package/dist/utils/format-relative-time.d.ts.map +0 -1
  502. package/src/utils/.dynamic-icons.md +0 -30
  503. package/src/utils/.format-relative-time.md +0 -36
  504. package/src/utils/dynamic-icons.tsx +0 -120
  505. package/src/utils/format-relative-time.ts +0 -52
  506. /package/dist/{chunk-N57KWHDB.js.map → chunk-CIPO6DXK.js.map} +0 -0
  507. /package/dist/components/chat/{block-card.d.ts → entity-cards/block-card.d.ts} +0 -0
  508. /package/dist/components/chat/{chat-ticket-item.d.ts → entity-cards/chat-ticket-item.d.ts} +0 -0
  509. /package/src/components/chat/{block-card.tsx → entity-cards/block-card.tsx} +0 -0
@@ -0,0 +1,139 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * Chat-identity capability hook.
5
+ *
6
+ * Surfaces the `{authTier, source, attachmentsEnabled}` bag for the
7
+ * CURRENT chat session so client code can gate UI elements (today: the
8
+ * `+` attachment button) on chat-side identity tiers WITHOUT sending a
9
+ * chat message first.
10
+ *
11
+ * Server-side parity: the route at `/api/chat/identity` runs the same
12
+ * 3-tier `requireChatAuth` chain the chat itself uses.
13
+ * `attachmentsEnabled` is computed server-side as
14
+ * `authTier !== 'anon' AND isSelfScopedSource(source)` — single
15
+ * source of truth, consumers don't combine the fields themselves.
16
+ *
17
+ * Implementation: plain `useEffect` + `useState` (NOT `useQuery`).
18
+ * Rationale:
19
+ * - Single consumer (`ChatAttachmentAddButton`), so react-query's
20
+ * dedup / cross-component cache benefit is zero.
21
+ * - The hook needs to re-fetch every time bearer-proxy creds change
22
+ * in localStorage. With react-query, this required a contrived
23
+ * `queryKey` that re-evaluated `getChatProxyAuth()` on every
24
+ * render — a layout-shift trap when HMR replaced the module
25
+ * mid-session (cache preserved across module reload but the
26
+ * queryKey computation lagged). Plain `useEffect` with the
27
+ * proxy email as a dep refetches reliably.
28
+ * - `chatAuthedFetch` carries the bearer-act-as headers so
29
+ * `/whoami`-authenticated admins resolve as `bearer-act-as` and
30
+ * get `attachmentsEnabled: true`.
31
+ *
32
+ * Endpoint URL: read from `useRequiredChatRuntime().endpoints.chatIdentityUrl`
33
+ * so embedded apps with their own reverse-proxy topology can override.
34
+ */
35
+
36
+ import { useEffect, useState } from 'react'
37
+ import { useRequiredChatRuntime } from '../../../contexts/chat-runtime-context'
38
+ import { chatAuthedFetch } from '../utils/chat-authed-fetch'
39
+ import { getChatProxyAuth } from '../utils/chat-proxy-auth-storage'
40
+
41
+ /**
42
+ * Wire-shape for the `/api/chat/identity` route response. Mirrors
43
+ * the hub's `ChatIdentityResponse` (in `app/api/chat/identity/route.ts`)
44
+ * — kept in sync there. Lib-side declaration so the chat panel can
45
+ * compile without depending on hub-internal types.
46
+ */
47
+ export interface ChatIdentityResponse {
48
+ authTier: 'session' | 'bearer-act-as' | 'anon'
49
+ source: string | null
50
+ attachmentsEnabled: boolean
51
+ /** Server-resolved display identity. `null` for anon. Read by the
52
+ * chat panel for the greeting first-name — embedders DON'T pass
53
+ * user info into the runtime; server is the single source of truth
54
+ * so the displayed name always matches the auth tier.
55
+ *
56
+ * All sub-fields are optional and may be `null`. Consumers MUST
57
+ * treat missing values as "use empty string and skip the affected
58
+ * UI line" — never substitute a placeholder. */
59
+ user: {
60
+ name: string | null
61
+ email: string | null
62
+ /** Optional first name supplied by the identity webservice.
63
+ * When set, the chat greeting renders `Hey ${firstName}, I'm Mingo`.
64
+ * When absent (null/undefined/empty), the greeting falls back to
65
+ * the no-name variant `Hey, I'm Mingo`. The chat panel does NOT
66
+ * derive `firstName` from `name.split(' ')[0]` anymore — this is
67
+ * the dedicated authoritative source from the identity webservice. */
68
+ firstName?: string | null
69
+ /** Optional last name. Currently unused by chat UI; surfaced for
70
+ * embedders that want to display the full name elsewhere. */
71
+ lastName?: string | null
72
+ /** Optional avatar URL. Validated as https:// server-side. */
73
+ avatarUrl?: string | null
74
+ } | null
75
+ }
76
+
77
+ /** Shape returned by the hook. NEVER throws — loading + error fall
78
+ * back to anon defaults so consumers can always render synchronously. */
79
+ export interface ChatIdentitySurface extends ChatIdentityResponse {
80
+ /** True while the query is in-flight on first mount; consumers that
81
+ * show a skeleton spinner can read this. */
82
+ isLoading: boolean
83
+ }
84
+
85
+ const ANON_DEFAULTS: ChatIdentityResponse = {
86
+ authTier: 'anon',
87
+ source: null,
88
+ attachmentsEnabled: false,
89
+ user: null,
90
+ }
91
+
92
+ export function useChatIdentity(): ChatIdentitySurface {
93
+ const runtime = useRequiredChatRuntime()
94
+ const url = runtime.endpoints.chatIdentityUrl
95
+ // `getChatProxyAuth()` reads localStorage every render. If the user
96
+ // pastes bearer creds mid-session (via the `/debug` creds bar),
97
+ // their email arrives here and the effect's dep changes → refetch.
98
+ const proxyEmail = getChatProxyAuth()?.email ?? null
99
+
100
+ const [data, setData] = useState<ChatIdentityResponse>(ANON_DEFAULTS)
101
+ const [isLoading, setIsLoading] = useState(true)
102
+
103
+ useEffect(() => {
104
+ let cancelled = false
105
+ const ctrl = new AbortController()
106
+
107
+ setIsLoading(true)
108
+ chatAuthedFetch(url, { signal: ctrl.signal })
109
+ .then(async (resp) => {
110
+ if (!resp.ok) return ANON_DEFAULTS
111
+ return (await resp.json()) as ChatIdentityResponse
112
+ })
113
+ .then((next) => {
114
+ if (cancelled) return
115
+ setData(next)
116
+ setIsLoading(false)
117
+ })
118
+ .catch((err) => {
119
+ // AbortError on unmount is expected; everything else falls
120
+ // back to anon defaults so the UI stays consistent.
121
+ if (cancelled) return
122
+ if ((err as Error).name !== 'AbortError') {
123
+ console.warn('[useChatIdentity] fetch failed, falling back to anon:', err)
124
+ }
125
+ setData(ANON_DEFAULTS)
126
+ setIsLoading(false)
127
+ })
128
+
129
+ return () => {
130
+ cancelled = true
131
+ ctrl.abort()
132
+ }
133
+ // `proxyEmail` in deps → refetch the moment the user pastes creds
134
+ // (or rotates them) and triggers a re-render. `url` is stable for
135
+ // the chat session but listed for completeness.
136
+ }, [url, proxyEmail])
137
+
138
+ return { ...data, isLoading }
139
+ }
@@ -0,0 +1,501 @@
1
+ 'use client'
2
+
3
+ import { useState, useCallback, useEffect, useRef } from 'react'
4
+ import { useSSE, type StreamFn, type StreamFnExtraOptions } from './use-sse'
5
+ import type {
6
+ Message,
7
+ MessageSegment,
8
+ ToolExecutionData,
9
+ } from '../types/message.types'
10
+ import { buildChatRefKey } from '../types/chat.types'
11
+ import type { ChatRef } from '../chat-ref.types'
12
+
13
+ export type { Message } from '../types/message.types'
14
+ export type { StreamFnExtraOptions } from './use-sse'
15
+
16
+ interface UseChatOptions {
17
+ useMock?: boolean
18
+ debugMode?: boolean
19
+ assistantName?: string
20
+ assistantAvatar?: string
21
+ /** Custom stream function — bypasses mock/SSE service when provided */
22
+ streamFn?: StreamFn
23
+ /** Initial messages (e.g., restored from localStorage). Evaluated once on mount. */
24
+ initialMessages?: Message[]
25
+ /** Called whenever the messages array changes — use for persistence. */
26
+ onMessagesChange?: (messages: Message[]) => void
27
+ }
28
+
29
+ function isToolSegment(
30
+ segment: MessageSegment,
31
+ ): segment is { type: 'tool_execution'; data: ToolExecutionData } {
32
+ return segment.type === 'tool_execution'
33
+ }
34
+
35
+ export function useChat({
36
+ useMock = true,
37
+ debugMode = false,
38
+ assistantName = 'Fae',
39
+ assistantAvatar,
40
+ streamFn,
41
+ initialMessages,
42
+ onMessagesChange,
43
+ }: UseChatOptions = {}) {
44
+ const [messages, setMessages] = useState<Message[]>(() => initialMessages ?? [])
45
+ const [isTyping, setIsTyping] = useState(false)
46
+ const currentAssistantSegmentsRef = useRef<MessageSegment[]>([])
47
+
48
+ // Notify the host whenever messages change so it can persist them.
49
+ const onMessagesChangeRef = useRef(onMessagesChange)
50
+ onMessagesChangeRef.current = onMessagesChange
51
+ useEffect(() => {
52
+ onMessagesChangeRef.current?.(messages)
53
+ }, [messages])
54
+
55
+ const {
56
+ streamMessage,
57
+ isStreaming,
58
+ error: sseError,
59
+ abort,
60
+ reset,
61
+ } = useSSE({
62
+ useMock,
63
+ debugMode,
64
+ streamFn,
65
+ })
66
+
67
+ const addMessage = useCallback((message: Message) => {
68
+ setMessages((prev) => [...prev, message])
69
+ }, [])
70
+
71
+ const updateLastAssistantMessage = useCallback((segments: MessageSegment[]) => {
72
+ setMessages((prev) => {
73
+ const newMessages = [...prev]
74
+ const lastMessage = newMessages[newMessages.length - 1]
75
+ if (lastMessage && lastMessage.role === 'assistant') {
76
+ newMessages[newMessages.length - 1] = {
77
+ ...lastMessage,
78
+ content: segments.length > 0 ? segments : '',
79
+ }
80
+ }
81
+ return newMessages
82
+ })
83
+ }, [])
84
+
85
+ const sendMessage = useCallback(
86
+ async (
87
+ text: string,
88
+ extra?: StreamFnExtraOptions,
89
+ /** When `hidden=true` the user message is added to the conversation
90
+ * history (so the LLM sees it as context) but NOT rendered in the
91
+ * UI. Used by the host to fire post-approval auto-continuation
92
+ * turns without polluting the visible thread with synthetic
93
+ * prompts like "(continue per protocol)". The assistant response
94
+ * IS rendered normally. */
95
+ options?: { hidden?: boolean },
96
+ ) => {
97
+ const userMessage: Message = {
98
+ id: `user-${Date.now()}`,
99
+ role: 'user',
100
+ name: 'You',
101
+ content: text,
102
+ timestamp: new Date(),
103
+ ...(options?.hidden ? { hidden: true } : {}),
104
+ }
105
+ addMessage(userMessage)
106
+
107
+ setIsTyping(true)
108
+ currentAssistantSegmentsRef.current = []
109
+
110
+ const assistantMessage: Message = {
111
+ id: `assistant-${Date.now()}`,
112
+ role: 'assistant',
113
+ name: assistantName,
114
+ content: [],
115
+ timestamp: new Date(),
116
+ avatar: assistantAvatar,
117
+ }
118
+ addMessage(assistantMessage)
119
+
120
+ try {
121
+ let receivedFirstTextChunk = false
122
+ let currentTextSegment = ''
123
+
124
+ for await (const segment of streamMessage(text, extra)) {
125
+ // Flip isTyping=false ONLY when the first TEXT segment arrives — NOT
126
+ // on a leading thinking-delta. Reason: <ThinkingDisplay> computes
127
+ // `isStreaming = (index === segments.length - 1 && isTyping)` and
128
+ // switches its label "Thinking" → "Thought" + drops PulseDots when
129
+ // isStreaming is false. If we flipped isTyping on the first thinking
130
+ // delta, the very first thinking chunk would render as "Thought"
131
+ // even while the model is still actively thinking. Holding isTyping
132
+ // true until real text starts keeps the live "Thinking…" UX correct.
133
+ if (!receivedFirstTextChunk && segment.type === 'text') {
134
+ setIsTyping(false)
135
+ receivedFirstTextChunk = true
136
+ }
137
+
138
+ if (segment.type === 'text') {
139
+ currentTextSegment += segment.text
140
+ const updatedSegments = [...currentAssistantSegmentsRef.current]
141
+
142
+ if (
143
+ updatedSegments.length > 0 &&
144
+ updatedSegments[updatedSegments.length - 1].type === 'text'
145
+ ) {
146
+ updatedSegments[updatedSegments.length - 1] = {
147
+ type: 'text',
148
+ text: currentTextSegment,
149
+ }
150
+ } else {
151
+ updatedSegments.push({ type: 'text', text: currentTextSegment })
152
+ }
153
+
154
+ currentAssistantSegmentsRef.current = updatedSegments
155
+ updateLastAssistantMessage(updatedSegments)
156
+ } else if (segment.type === 'thinking') {
157
+ // Adaptive-thinking content from the model. Stash as a single
158
+ // 'thinking' segment at the front of the message; if the segment
159
+ // already exists (server flushed thinking in chunks via the
160
+ // leading-frame loop), replace its text. Order matters: thinking
161
+ // ALWAYS precedes the answer text so the OSS-lib renders the
162
+ // ThinkingDisplay card above the answer body.
163
+ const updatedSegments = [...currentAssistantSegmentsRef.current]
164
+ const existingThinkingIdx = updatedSegments.findIndex(
165
+ (s) => s.type === 'thinking',
166
+ )
167
+ if (existingThinkingIdx !== -1) {
168
+ updatedSegments[existingThinkingIdx] = {
169
+ type: 'thinking',
170
+ text: segment.text,
171
+ }
172
+ } else {
173
+ // Insert at the FRONT so it renders before any text accumulated.
174
+ updatedSegments.unshift({ type: 'thinking', text: segment.text })
175
+ }
176
+ currentAssistantSegmentsRef.current = updatedSegments
177
+ updateLastAssistantMessage(updatedSegments)
178
+ } else if ((segment as any).type === 'approval_request') {
179
+ // Tool proposal from the server. The streamFn pre-wired
180
+ // `onApprove`/`onReject` so they POST to
181
+ // `/api/chat/agent/confirm-tool` with the same proxy auth the
182
+ // chat stream used. Here we (1) flip the card's `status` from
183
+ // pending → approved/rejected after the network round-trip,
184
+ // and (2) append a follow-up TEXT segment so the user sees a
185
+ // concrete confirmation of what happened.
186
+ if (currentTextSegment) {
187
+ const updated = [...currentAssistantSegmentsRef.current]
188
+ if (updated.length > 0 && updated[updated.length - 1].type === 'text') {
189
+ updated[updated.length - 1] = { type: 'text', text: currentTextSegment }
190
+ } else {
191
+ updated.push({ type: 'text', text: currentTextSegment })
192
+ }
193
+ currentAssistantSegmentsRef.current = updated
194
+ currentTextSegment = ''
195
+ }
196
+ const seg = segment as any
197
+ const proposalId: string = seg.data?.requestId
198
+ // Locate the assistant message that hosts this approval
199
+ // segment and apply a transform — INDEPENDENT of
200
+ // `currentAssistantSegmentsRef`, which the SSE `finally`
201
+ // resets to `[]` the moment the stream ends. If we mutated
202
+ // the ref then re-rendered `updateLastAssistantMessage([])`
203
+ // (the empty ref's snapshot), we'd wipe the assistant
204
+ // message's content the instant the user clicks Approve.
205
+ const updateApprovalMessage = (
206
+ transform: (segments: MessageSegment[]) => MessageSegment[],
207
+ ) => {
208
+ setMessages((prev) => {
209
+ for (let i = prev.length - 1; i >= 0; i--) {
210
+ const m = prev[i]
211
+ if (m.role !== 'assistant') continue
212
+ if (!Array.isArray(m.content)) continue
213
+ const segments = m.content as MessageSegment[]
214
+ const hasMatch = segments.some(
215
+ (s) =>
216
+ (s as any).type === 'approval_request' &&
217
+ (s as any).data?.requestId === proposalId,
218
+ )
219
+ if (!hasMatch) continue
220
+ const next = [...prev]
221
+ next[i] = { ...m, content: transform(segments) }
222
+ return next
223
+ }
224
+ return prev
225
+ })
226
+ }
227
+ // Server-driven post-approve flow: wrappedApprove/Reject just
228
+ // fire a new chat turn with `approvalAction` set. The streamFn
229
+ // routes that turn to `/api/chat/agent/confirm-tool` which
230
+ // returns SSE — its `decision_resolved` leading frame lands
231
+ // back as a `type: 'decision_resolved'` segment in this same
232
+ // loop, where the handler below matches it back to this
233
+ // approval card via `requestId` and applies status flip +
234
+ // receipt append. NO client-side orchestration.
235
+ const wrappedApprove = async (reqId?: string) => {
236
+ if (!reqId) return
237
+ await sendMessage(
238
+ '',
239
+ { approvalAction: { proposalId: reqId, action: 'approve' } },
240
+ { hidden: true },
241
+ )
242
+ }
243
+ const wrappedReject = async (reqId?: string) => {
244
+ if (!reqId) return
245
+ await sendMessage(
246
+ '',
247
+ { approvalAction: { proposalId: reqId, action: 'reject' } },
248
+ { hidden: true },
249
+ )
250
+ }
251
+ currentAssistantSegmentsRef.current.push({
252
+ ...seg,
253
+ onApprove: wrappedApprove,
254
+ onReject: wrappedReject,
255
+ })
256
+ updateLastAssistantMessage([...currentAssistantSegmentsRef.current])
257
+ } else if ((segment as any).type === 'decision_resolved') {
258
+ // Server-driven decision frame from /api/chat/agent/confirm-tool.
259
+ //
260
+ // Two side-effects:
261
+ //
262
+ // 1. SOURCE message (the one carrying the approval card):
263
+ // flip the matched approval_request segment's status to
264
+ // 'approved'/'rejected'.
265
+ //
266
+ // 2. CURRENT (new) assistant message: prepend the receipt
267
+ // ("✅ Approved — ticket created: <card>" etc.) into
268
+ // `currentTextSegment`. Subsequent auto-continuation
269
+ // text deltas extend the same segment.
270
+ //
271
+ // For reject, no auto-continuation text follows — the new
272
+ // turn carries only the receipt.
273
+ const decision = segment as unknown as {
274
+ type: 'decision_resolved'
275
+ proposalId?: string
276
+ action: 'approved' | 'rejected'
277
+ ok: boolean
278
+ toolName?: string
279
+ result?: { ticket_id?: string; status?: string | null }
280
+ marker?: string
281
+ /** Full ChatRef payload from the server's `decision_resolved`
282
+ * frame — `card.ref` in the wire format. Carries enough
283
+ * metadata for inline card render. */
284
+ cardRef?: {
285
+ type?: string
286
+ id?: string
287
+ title?: string
288
+ url?: string | null
289
+ metadata?: Record<string, string | null | undefined>
290
+ [key: string]: unknown
291
+ }
292
+ /** Server-rendered receipt copy. Computed by the per-source
293
+ * `strategy.tools.receiptRenderer(...)`. */
294
+ receiptText?: string
295
+ /** True when the server WILL stream an auto-continuation
296
+ * Sonnet turn after this frame. */
297
+ willAutoContinue?: boolean
298
+ }
299
+ if (!decision.proposalId) continue
300
+ // Step 1 — flip the source card's status.
301
+ setMessages((prev) => {
302
+ for (let i = prev.length - 1; i >= 0; i--) {
303
+ const m = prev[i]
304
+ if (m.role !== 'assistant') continue
305
+ if (!Array.isArray(m.content)) continue
306
+ const segments = m.content as MessageSegment[]
307
+ const hasMatch = segments.some(
308
+ (s) =>
309
+ (s as any).type === 'approval_request' &&
310
+ (s as any).data?.requestId === decision.proposalId,
311
+ )
312
+ if (!hasMatch) continue
313
+ const flipped = segments.map((s) =>
314
+ (s as any).type === 'approval_request' &&
315
+ (s as any).data?.requestId === decision.proposalId
316
+ ? ({ ...(s as any), status: decision.action } as MessageSegment)
317
+ : s,
318
+ )
319
+ const next = [...prev]
320
+ next[i] = { ...m, content: flipped }
321
+ return next
322
+ }
323
+ return prev
324
+ })
325
+ // Step 2 — receipt text into the CURRENT message.
326
+ // SERVER-RENDERED. The per-source strategy
327
+ // (`strategy.tools.receiptRenderer(...)`) computed the copy
328
+ // and shipped it on the SSE frame as `receiptText`. The
329
+ // chat-shell is source-agnostic — it just appends the string.
330
+ const receipt = decision.receiptText ?? null
331
+ if (receipt === null) {
332
+ // No server-provided copy → don't fabricate a fallback.
333
+ continue
334
+ }
335
+ currentTextSegment = receipt + '\n\n'
336
+ const updatedSegments = [...currentAssistantSegmentsRef.current]
337
+ if (
338
+ updatedSegments.length > 0 &&
339
+ updatedSegments[updatedSegments.length - 1].type === 'text'
340
+ ) {
341
+ updatedSegments[updatedSegments.length - 1] = {
342
+ type: 'text',
343
+ text: currentTextSegment,
344
+ }
345
+ } else {
346
+ updatedSegments.push({ type: 'text', text: currentTextSegment })
347
+ }
348
+ currentAssistantSegmentsRef.current = updatedSegments
349
+ // SERVER-DRIVEN CARDREF ATTACHMENT — stamp the ref onto THIS
350
+ // assistant message so the `[card://<type>:<id>]` marker
351
+ // resolves via `message.chatRefs` independent of per-turn
352
+ // refsMap indexing.
353
+ const refForMessage =
354
+ decision.cardRef &&
355
+ typeof decision.cardRef.type === 'string' &&
356
+ typeof decision.cardRef.id === 'string'
357
+ ? decision.cardRef
358
+ : null
359
+ if (refForMessage) {
360
+ const refKey = buildChatRefKey(
361
+ refForMessage.type as string,
362
+ refForMessage.id as string,
363
+ )
364
+ setMessages((prev) => {
365
+ const next = [...prev]
366
+ const lastIdx = next.length - 1
367
+ const lastMsg = next[lastIdx]
368
+ if (!lastMsg || lastMsg.role !== 'assistant') return prev
369
+ next[lastIdx] = {
370
+ ...lastMsg,
371
+ content: updatedSegments.length > 0 ? updatedSegments : '',
372
+ chatRefs: {
373
+ ...(lastMsg.chatRefs ?? {}),
374
+ [refKey]: refForMessage as unknown as ChatRef,
375
+ },
376
+ }
377
+ return next
378
+ })
379
+ } else {
380
+ updateLastAssistantMessage(updatedSegments)
381
+ }
382
+ } else if (segment.type === 'tool_execution') {
383
+ if (currentTextSegment) {
384
+ const updatedSegments = [...currentAssistantSegmentsRef.current]
385
+
386
+ if (
387
+ updatedSegments.length > 0 &&
388
+ updatedSegments[updatedSegments.length - 1].type === 'text'
389
+ ) {
390
+ updatedSegments[updatedSegments.length - 1] = {
391
+ type: 'text',
392
+ text: currentTextSegment,
393
+ }
394
+ } else {
395
+ updatedSegments.push({ type: 'text', text: currentTextSegment })
396
+ }
397
+
398
+ currentAssistantSegmentsRef.current = updatedSegments
399
+ currentTextSegment = ''
400
+ }
401
+
402
+ const existingToolIndex = currentAssistantSegmentsRef.current.findIndex(
403
+ (s): s is { type: 'tool_execution'; data: ToolExecutionData } =>
404
+ isToolSegment(s) &&
405
+ s.data.type === 'EXECUTING_TOOL' &&
406
+ s.data.integratedToolType === segment.data.integratedToolType &&
407
+ s.data.toolFunction === segment.data.toolFunction,
408
+ )
409
+
410
+ if (existingToolIndex !== -1 && segment.data.type === 'EXECUTED_TOOL') {
411
+ const existingTool = currentAssistantSegmentsRef.current[existingToolIndex] as {
412
+ type: 'tool_execution'
413
+ data: ToolExecutionData
414
+ }
415
+ currentAssistantSegmentsRef.current[existingToolIndex] = {
416
+ ...segment,
417
+ data: {
418
+ ...segment.data,
419
+ parameters: segment.data.parameters || existingTool.data.parameters,
420
+ },
421
+ }
422
+ } else {
423
+ currentAssistantSegmentsRef.current.push(segment)
424
+ }
425
+
426
+ updateLastAssistantMessage([...currentAssistantSegmentsRef.current])
427
+ }
428
+ }
429
+ } catch (err) {
430
+ const errorMessage: Message = {
431
+ id: `error-${Date.now()}`,
432
+ role: 'error',
433
+ content:
434
+ err instanceof Error
435
+ ? err.message
436
+ : 'An error occurred while processing your request.',
437
+ timestamp: new Date(),
438
+ }
439
+ setMessages((prev) => [...prev.slice(0, -1), errorMessage])
440
+ } finally {
441
+ setIsTyping(false)
442
+ // Reject-path on confirm-tool emits ONLY a `decision_resolved`
443
+ // leading frame and closes — no text segments stream in, so the
444
+ // placeholder assistant message added by addMessage above would
445
+ // render as a blank bubble. Remove the trailing assistant message
446
+ // if it still has no segments.
447
+ const trailingIsEmpty =
448
+ Array.isArray(currentAssistantSegmentsRef.current) &&
449
+ currentAssistantSegmentsRef.current.length === 0
450
+ if (trailingIsEmpty) {
451
+ setMessages((prev) => {
452
+ if (prev.length === 0) return prev
453
+ const last = prev[prev.length - 1]
454
+ if (last.role !== 'assistant') return prev
455
+ if (Array.isArray(last.content) && last.content.length > 0) return prev
456
+ if (typeof last.content === 'string' && last.content.length > 0) return prev
457
+ return prev.slice(0, -1)
458
+ })
459
+ }
460
+ currentAssistantSegmentsRef.current = []
461
+ }
462
+ },
463
+ [streamMessage, addMessage, updateLastAssistantMessage, assistantName, assistantAvatar],
464
+ )
465
+
466
+ const handleQuickAction = useCallback(
467
+ (actionText: string) => {
468
+ sendMessage(actionText)
469
+ },
470
+ [sendMessage],
471
+ )
472
+
473
+ const clearMessages = useCallback(() => {
474
+ setMessages([])
475
+ setIsTyping(false)
476
+ reset()
477
+ }, [reset])
478
+
479
+ /**
480
+ * Abort the in-flight streamed message. The fetch's AbortSignal terminates
481
+ * the upstream Anthropic request (so billing stops); the `for await` loop
482
+ * inside `sendMessage` exits via `useSSE`'s AbortError handling, leaving
483
+ * the partial assistant response visible to the user.
484
+ */
485
+ const stopMessage = useCallback(() => {
486
+ abort()
487
+ setIsTyping(false)
488
+ }, [abort])
489
+
490
+ return {
491
+ messages,
492
+ isTyping,
493
+ isStreaming,
494
+ error: sseError,
495
+ sendMessage,
496
+ stopMessage,
497
+ handleQuickAction,
498
+ clearMessages,
499
+ hasMessages: messages.length > 0,
500
+ }
501
+ }