@flamingo-stack/openframe-frontend-core 0.0.467 → 0.0.468-snapshot.20260723140929

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 (289) hide show
  1. package/dist/chat-protocol/decode.d.ts +58 -0
  2. package/dist/chat-protocol/decode.d.ts.map +1 -0
  3. package/dist/chat-protocol/encode.d.ts +44 -0
  4. package/dist/chat-protocol/encode.d.ts.map +1 -0
  5. package/dist/chat-protocol/env-flag.d.ts +35 -0
  6. package/dist/chat-protocol/env-flag.d.ts.map +1 -0
  7. package/dist/chat-protocol/events.d.ts +192 -0
  8. package/dist/chat-protocol/events.d.ts.map +1 -0
  9. package/dist/chat-protocol/frames.d.ts +206 -0
  10. package/dist/chat-protocol/frames.d.ts.map +1 -0
  11. package/dist/chat-protocol/index.cjs +493 -0
  12. package/dist/chat-protocol/index.cjs.map +1 -0
  13. package/dist/chat-protocol/index.d.ts +18 -0
  14. package/dist/chat-protocol/index.d.ts.map +1 -0
  15. package/dist/chat-protocol/index.js +477 -0
  16. package/dist/chat-protocol/index.js.map +1 -0
  17. package/dist/chat-protocol/ip-normalize.d.ts +44 -0
  18. package/dist/chat-protocol/ip-normalize.d.ts.map +1 -0
  19. package/dist/chat-protocol/nats-decoder.d.ts +26 -0
  20. package/dist/chat-protocol/nats-decoder.d.ts.map +1 -0
  21. package/dist/{chunk-BIDOIPIT.js → chunk-2BJSRTKU.js} +2 -2
  22. package/dist/{chunk-4DFPQKKJ.js → chunk-33FDAZDB.js} +2 -2
  23. package/dist/{chunk-LOWJWKM5.js → chunk-4QDFNDVW.js} +4 -4
  24. package/dist/{chunk-72NEN4G4.cjs → chunk-4UFRQT7Z.cjs} +15 -15
  25. package/dist/{chunk-72NEN4G4.cjs.map → chunk-4UFRQT7Z.cjs.map} +1 -1
  26. package/dist/{chunk-WWC75D3J.cjs → chunk-4W54HUP7.cjs} +6853 -4609
  27. package/dist/chunk-4W54HUP7.cjs.map +1 -0
  28. package/dist/{chunk-6DZ5QOUM.cjs → chunk-5HUTT3FD.cjs} +11 -11
  29. package/dist/{chunk-6DZ5QOUM.cjs.map → chunk-5HUTT3FD.cjs.map} +1 -1
  30. package/dist/{chunk-GXXLJHQX.js → chunk-7I2QMUEZ.js} +2 -2
  31. package/dist/{chunk-QJ7NIL6A.js → chunk-AJSNF5YF.js} +6 -5
  32. package/dist/chunk-AJSNF5YF.js.map +1 -0
  33. package/dist/{chunk-NYOQNYSI.js → chunk-AW3LVWVV.js} +2 -2
  34. package/dist/{chunk-25YYEVSE.js → chunk-DG7TX763.js} +2 -2
  35. package/dist/{chunk-CZFPPNYV.js → chunk-E6O6XATC.js} +11899 -9655
  36. package/dist/chunk-E6O6XATC.js.map +1 -0
  37. package/dist/{chunk-ZYPHZ3R3.cjs → chunk-GLKULDQN.cjs} +9 -9
  38. package/dist/{chunk-ZYPHZ3R3.cjs.map → chunk-GLKULDQN.cjs.map} +1 -1
  39. package/dist/{chunk-TZSPLSDU.js → chunk-GYEZV4GK.js} +2 -2
  40. package/dist/{chunk-G5D7NRH5.cjs → chunk-LRESZO4L.cjs} +26 -26
  41. package/dist/{chunk-G5D7NRH5.cjs.map → chunk-LRESZO4L.cjs.map} +1 -1
  42. package/dist/{chunk-ABU37QSG.js → chunk-MMF6HJB7.js} +4 -4
  43. package/dist/{chunk-O7LQYYUA.cjs → chunk-MTLBBSLP.cjs} +5 -5
  44. package/dist/{chunk-O7LQYYUA.cjs.map → chunk-MTLBBSLP.cjs.map} +1 -1
  45. package/dist/{chunk-UWW4PQQS.cjs → chunk-OVIUQJ2H.cjs} +28 -27
  46. package/dist/chunk-OVIUQJ2H.cjs.map +1 -0
  47. package/dist/{chunk-3L44PPMF.js → chunk-RPAOSHBN.js} +2 -2
  48. package/dist/{chunk-VERK32MO.cjs → chunk-TOFOK7G5.cjs} +37 -37
  49. package/dist/{chunk-VERK32MO.cjs.map → chunk-TOFOK7G5.cjs.map} +1 -1
  50. package/dist/{chunk-QITN43HN.cjs → chunk-U2KPMWO6.cjs} +7 -7
  51. package/dist/{chunk-QITN43HN.cjs.map → chunk-U2KPMWO6.cjs.map} +1 -1
  52. package/dist/{chunk-YGW7T57C.cjs → chunk-V5YWOQBP.cjs} +31 -31
  53. package/dist/{chunk-YGW7T57C.cjs.map → chunk-V5YWOQBP.cjs.map} +1 -1
  54. package/dist/{chunk-ILZ66CS6.js → chunk-VUCYS36H.js} +10 -10
  55. package/dist/chunk-VUCYS36H.js.map +1 -0
  56. package/dist/{chunk-SGDXS7VT.cjs → chunk-WHWDGCQV.cjs} +60 -60
  57. package/dist/chunk-WHWDGCQV.cjs.map +1 -0
  58. package/dist/{chunk-G2H4AKL3.cjs → chunk-YXNWEVER.cjs} +62 -62
  59. package/dist/{chunk-G2H4AKL3.cjs.map → chunk-YXNWEVER.cjs.map} +1 -1
  60. package/dist/components/case-studies/index.cjs +8 -8
  61. package/dist/components/case-studies/index.js +2 -2
  62. package/dist/components/chat/chat-composer.d.ts +8 -1
  63. package/dist/components/chat/chat-composer.d.ts.map +1 -1
  64. package/dist/components/chat/chat-context-memory-bar.d.ts +37 -0
  65. package/dist/components/chat/chat-context-memory-bar.d.ts.map +1 -0
  66. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  67. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  68. package/dist/components/chat/embeddable-chat.d.ts +14 -6
  69. package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
  70. package/dist/components/chat/hooks/index.d.ts +0 -1
  71. package/dist/components/chat/hooks/index.d.ts.map +1 -1
  72. package/dist/components/chat/hooks/use-chat.d.ts.map +1 -1
  73. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +15 -48
  74. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
  75. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +3 -47
  76. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
  77. package/dist/components/chat/index.cjs +12 -2
  78. package/dist/components/chat/index.cjs.map +1 -1
  79. package/dist/components/chat/index.d.ts +2 -0
  80. package/dist/components/chat/index.d.ts.map +1 -1
  81. package/dist/components/chat/index.js +23 -13
  82. package/dist/components/chat/stream/chat-dialog-store.d.ts +184 -0
  83. package/dist/components/chat/stream/chat-dialog-store.d.ts.map +1 -0
  84. package/dist/components/chat/stream/chat-stream-reducer.d.ts +367 -0
  85. package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +1 -0
  86. package/dist/components/chat/stream/delta-batcher.d.ts +51 -0
  87. package/dist/components/chat/stream/delta-batcher.d.ts.map +1 -0
  88. package/dist/components/chat/stream/index.d.ts +17 -0
  89. package/dist/components/chat/stream/index.d.ts.map +1 -0
  90. package/dist/components/chat/stream/message-mutations.d.ts +77 -0
  91. package/dist/components/chat/stream/message-mutations.d.ts.map +1 -0
  92. package/dist/components/chat/stream/use-chat-stream-reducer.d.ts +22 -0
  93. package/dist/components/chat/stream/use-chat-stream-reducer.d.ts.map +1 -0
  94. package/dist/components/chat/types/api.types.d.ts +1 -81
  95. package/dist/components/chat/types/api.types.d.ts.map +1 -1
  96. package/dist/components/chat/types/processing.types.d.ts +2 -90
  97. package/dist/components/chat/types/processing.types.d.ts.map +1 -1
  98. package/dist/components/chat/utils/extract-incomplete-message-state.d.ts +34 -6
  99. package/dist/components/chat/utils/extract-incomplete-message-state.d.ts.map +1 -1
  100. package/dist/components/chat/utils/index.d.ts +2 -3
  101. package/dist/components/chat/utils/index.d.ts.map +1 -1
  102. package/dist/components/chat/utils/process-historical-messages.d.ts +59 -11
  103. package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
  104. package/dist/components/contact/index.cjs +3 -3
  105. package/dist/components/contact/index.js +2 -2
  106. package/dist/components/docs/index.cjs +5 -5
  107. package/dist/components/docs/index.js +4 -4
  108. package/dist/components/embeds/index.cjs +3 -3
  109. package/dist/components/embeds/index.js +2 -2
  110. package/dist/components/faq/index.cjs +3 -3
  111. package/dist/components/faq/index.js +2 -2
  112. package/dist/components/features/index.cjs +2 -2
  113. package/dist/components/features/index.js +1 -1
  114. package/dist/components/help-center-pages/index.cjs +20 -20
  115. package/dist/components/help-center-pages/index.js +11 -11
  116. package/dist/components/index.cjs +174 -130
  117. package/dist/components/index.cjs.map +1 -1
  118. package/dist/components/index.js +65 -21
  119. package/dist/components/index.js.map +1 -1
  120. package/dist/components/navigation/index.cjs +2 -2
  121. package/dist/components/navigation/index.js +1 -1
  122. package/dist/components/onboarding-guides/index.cjs +5 -5
  123. package/dist/components/onboarding-guides/index.js +4 -4
  124. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
  125. package/dist/components/related-content/index.cjs +3 -3
  126. package/dist/components/related-content/index.js +2 -2
  127. package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
  128. package/dist/components/tickets/index.cjs +5 -5
  129. package/dist/components/tickets/index.js +4 -4
  130. package/dist/components/ui/index.cjs +46 -2
  131. package/dist/components/ui/index.cjs.map +1 -1
  132. package/dist/components/ui/index.d.ts +1 -2
  133. package/dist/components/ui/index.d.ts.map +1 -1
  134. package/dist/components/ui/index.js +57 -13
  135. package/dist/components/ui/markdown/base-components.d.ts +56 -0
  136. package/dist/components/ui/markdown/base-components.d.ts.map +1 -0
  137. package/dist/components/ui/markdown/engine.d.ts +99 -0
  138. package/dist/components/ui/markdown/engine.d.ts.map +1 -0
  139. package/dist/components/ui/markdown/heading-ids.d.ts +65 -0
  140. package/dist/components/ui/markdown/heading-ids.d.ts.map +1 -0
  141. package/dist/components/ui/markdown/index.d.ts +18 -0
  142. package/dist/components/ui/markdown/index.d.ts.map +1 -0
  143. package/dist/components/ui/markdown/mermaid-diagram.d.ts +79 -0
  144. package/dist/components/ui/markdown/mermaid-diagram.d.ts.map +1 -0
  145. package/dist/components/ui/markdown/rich/embed-overrides.d.ts +14 -0
  146. package/dist/components/ui/markdown/rich/embed-overrides.d.ts.map +1 -0
  147. package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts +40 -0
  148. package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts.map +1 -0
  149. package/dist/components/ui/markdown/rich/shortcodes.d.ts +8 -0
  150. package/dist/components/ui/markdown/rich/shortcodes.d.ts.map +1 -0
  151. package/dist/components/ui/markdown/sanitize.d.ts +153 -0
  152. package/dist/components/ui/markdown/sanitize.d.ts.map +1 -0
  153. package/dist/components/ui/markdown/simple-markdown-renderer.d.ts +23 -0
  154. package/dist/components/ui/markdown/simple-markdown-renderer.d.ts.map +1 -0
  155. package/dist/components/ui/markdown/streaming.d.ts +78 -0
  156. package/dist/components/ui/markdown/streaming.d.ts.map +1 -0
  157. package/dist/components/ui/markdown/text-size.d.ts +34 -0
  158. package/dist/components/ui/markdown/text-size.d.ts.map +1 -0
  159. package/dist/index.cjs +62 -2
  160. package/dist/index.cjs.map +1 -1
  161. package/dist/index.js +73 -13
  162. package/dist/utils/index.cjs +169 -40
  163. package/dist/utils/index.cjs.map +1 -1
  164. package/dist/utils/index.d.ts +1 -0
  165. package/dist/utils/index.d.ts.map +1 -1
  166. package/dist/utils/index.js +162 -41
  167. package/dist/utils/index.js.map +1 -1
  168. package/dist/utils/markdown-fences.d.ts +42 -0
  169. package/dist/utils/markdown-fences.d.ts.map +1 -0
  170. package/dist/utils/markdown-heading-id.d.ts +85 -0
  171. package/dist/utils/markdown-heading-id.d.ts.map +1 -0
  172. package/dist/utils/markdown-section-extractor.d.ts.map +1 -1
  173. package/package.json +7 -1
  174. package/src/chat-protocol/__tests__/__snapshots__/nats-decoder-golden.test.ts.snap +307 -0
  175. package/src/chat-protocol/__tests__/chat-protocol.test.ts +515 -0
  176. package/src/chat-protocol/__tests__/env-flag.test.ts +52 -0
  177. package/src/chat-protocol/__tests__/ip-normalize.test.ts +136 -0
  178. package/src/chat-protocol/__tests__/nats-decoder-golden.test.ts +228 -0
  179. package/src/chat-protocol/decode.ts +277 -0
  180. package/src/chat-protocol/encode.ts +71 -0
  181. package/src/chat-protocol/env-flag.ts +39 -0
  182. package/src/chat-protocol/events.ts +228 -0
  183. package/src/chat-protocol/frames.ts +238 -0
  184. package/src/chat-protocol/index.ts +21 -0
  185. package/src/chat-protocol/ip-normalize.ts +146 -0
  186. package/src/chat-protocol/nats-decoder.ts +252 -0
  187. package/src/components/chat/__tests__/chat-message-list.test.tsx +293 -5
  188. package/src/components/chat/__tests__/chat-message-streaming-memo.test.tsx +207 -0
  189. package/src/components/chat/__tests__/chat-pending-turn.test.tsx +209 -0
  190. package/src/components/chat/chat-composer.tsx +32 -5
  191. package/src/components/chat/chat-context-memory-bar.tsx +159 -0
  192. package/src/components/chat/chat-message-enhanced.tsx +111 -17
  193. package/src/components/chat/chat-message-list.tsx +358 -109
  194. package/src/components/chat/embeddable-chat.tsx +23 -15
  195. package/src/components/chat/hooks/.index.md +1 -1
  196. package/src/components/chat/hooks/.use-nats-chat-adapter.md +1 -1
  197. package/src/components/chat/hooks/__tests__/__snapshots__/persisted-state-v1-golden.test.ts.snap +297 -0
  198. package/src/components/chat/hooks/__tests__/__snapshots__/sse-stream-golden.test.ts.snap +0 -0
  199. package/src/components/chat/hooks/__tests__/persisted-state-v1-golden.test.ts +272 -0
  200. package/src/components/chat/hooks/__tests__/sse-stream-golden.test.ts +318 -0
  201. package/src/components/chat/hooks/index.ts +0 -1
  202. package/src/components/chat/hooks/use-chat.ts +8 -0
  203. package/src/components/chat/hooks/use-nats-chat-adapter.ts +243 -822
  204. package/src/components/chat/hooks/use-sse-chat-adapter.ts +318 -666
  205. package/src/components/chat/index.ts +6 -0
  206. package/src/components/chat/stream/__tests__/__snapshots__/chat-stream-reducer-golden.test.ts.snap +937 -0
  207. package/src/components/chat/stream/__tests__/chat-dialog-store.test.ts +756 -0
  208. package/src/components/chat/stream/__tests__/chat-stream-reducer-golden.test.ts +460 -0
  209. package/src/components/chat/stream/__tests__/chat-stream-reducer.test.ts +894 -0
  210. package/src/components/chat/stream/__tests__/delta-batcher.test.ts +255 -0
  211. package/src/components/chat/stream/__tests__/use-chat-stream-reducer.test.ts +98 -0
  212. package/src/components/chat/stream/chat-dialog-store.ts +536 -0
  213. package/src/components/chat/stream/chat-stream-reducer.ts +1796 -0
  214. package/src/components/chat/stream/delta-batcher.ts +159 -0
  215. package/src/components/chat/stream/index.ts +55 -0
  216. package/src/components/chat/stream/message-mutations.ts +338 -0
  217. package/src/components/chat/stream/use-chat-stream-reducer.ts +126 -0
  218. package/src/components/chat/thinking-display.tsx +1 -1
  219. package/src/components/chat/types/.api.types.md +1 -3
  220. package/src/components/chat/types/.processing.types.md +6 -23
  221. package/src/components/chat/types/api.types.ts +6 -73
  222. package/src/components/chat/types/processing.types.ts +11 -52
  223. package/src/components/chat/utils/.index.md +0 -5
  224. package/src/components/chat/utils/__tests__/__snapshots__/process-historical-messages-golden.test.ts.snap +418 -0
  225. package/src/components/chat/utils/__tests__/__snapshots__/segment-accumulator-golden.test.ts.snap +599 -0
  226. package/src/components/chat/utils/__tests__/process-historical-messages-golden.test.ts +317 -0
  227. package/src/components/chat/utils/__tests__/segment-accumulator-golden.test.ts +270 -0
  228. package/src/components/chat/utils/extract-incomplete-message-state.ts +63 -5
  229. package/src/components/chat/utils/index.ts +5 -8
  230. package/src/components/chat/utils/process-historical-messages.ts +352 -383
  231. package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +22 -4
  232. package/src/components/shared/legal-document/legal-document-page.tsx +1 -1
  233. package/src/components/shared/product-release/release-detail-page.tsx +19 -4
  234. package/src/components/ui/__tests__/__snapshots__/markdown-parity.test.tsx.snap +2420 -0
  235. package/src/components/ui/__tests__/markdown-parity.test.tsx +2528 -0
  236. package/src/components/ui/index.ts +1 -2
  237. package/src/components/ui/markdown/__tests__/mermaid-security.test.ts +115 -0
  238. package/src/components/ui/markdown/__tests__/mermaid-stale-render.test.tsx +95 -0
  239. package/src/components/ui/markdown/__tests__/sanitize-invariant.test.ts +309 -0
  240. package/src/components/ui/markdown/__tests__/streaming.test.tsx +388 -0
  241. package/src/components/ui/markdown/base-components.tsx +341 -0
  242. package/src/components/ui/markdown/engine.tsx +315 -0
  243. package/src/components/ui/markdown/heading-ids.ts +239 -0
  244. package/src/components/ui/markdown/index.ts +49 -0
  245. package/src/components/ui/markdown/mermaid-diagram.tsx +291 -0
  246. package/src/components/ui/markdown/rich/embed-overrides.tsx +199 -0
  247. package/src/components/ui/markdown/rich/rich-markdown-renderer.tsx +184 -0
  248. package/src/components/ui/markdown/rich/shortcodes.ts +170 -0
  249. package/src/components/ui/markdown/sanitize.ts +3499 -0
  250. package/src/components/ui/markdown/simple-markdown-renderer.tsx +28 -0
  251. package/src/components/ui/markdown/streaming.ts +362 -0
  252. package/src/components/ui/markdown/text-size.ts +106 -0
  253. package/src/components/ui/release-changelog-section.tsx +1 -1
  254. package/src/components/ui/tab-selector.tsx +8 -8
  255. package/src/components/ui/ticket-info-section.tsx +1 -1
  256. package/src/utils/index.ts +1 -0
  257. package/src/utils/markdown-fences.ts +127 -0
  258. package/src/utils/markdown-heading-id.ts +348 -0
  259. package/src/utils/markdown-section-extractor.ts +41 -56
  260. package/dist/chunk-CZFPPNYV.js.map +0 -1
  261. package/dist/chunk-ILZ66CS6.js.map +0 -1
  262. package/dist/chunk-QJ7NIL6A.js.map +0 -1
  263. package/dist/chunk-SGDXS7VT.cjs.map +0 -1
  264. package/dist/chunk-UWW4PQQS.cjs.map +0 -1
  265. package/dist/chunk-WWC75D3J.cjs.map +0 -1
  266. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts +0 -6
  267. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +0 -1
  268. package/dist/components/chat/utils/chunk-parser.d.ts +0 -25
  269. package/dist/components/chat/utils/chunk-parser.d.ts.map +0 -1
  270. package/dist/components/ui/rich-markdown-renderer.d.ts +0 -34
  271. package/dist/components/ui/rich-markdown-renderer.d.ts.map +0 -1
  272. package/dist/components/ui/simple-markdown-renderer.d.ts +0 -73
  273. package/dist/components/ui/simple-markdown-renderer.d.ts.map +0 -1
  274. package/src/components/chat/hooks/.use-realtime-chunk-processor.md +0 -50
  275. package/src/components/chat/hooks/use-realtime-chunk-processor.ts +0 -479
  276. package/src/components/chat/utils/.chunk-parser.md +0 -51
  277. package/src/components/chat/utils/chunk-parser.ts +0 -255
  278. package/src/components/ui/.simple-markdown-renderer.md +0 -40
  279. package/src/components/ui/rich-markdown-renderer.tsx +0 -1223
  280. package/src/components/ui/simple-markdown-renderer.tsx +0 -965
  281. /package/dist/{chunk-BIDOIPIT.js.map → chunk-2BJSRTKU.js.map} +0 -0
  282. /package/dist/{chunk-4DFPQKKJ.js.map → chunk-33FDAZDB.js.map} +0 -0
  283. /package/dist/{chunk-LOWJWKM5.js.map → chunk-4QDFNDVW.js.map} +0 -0
  284. /package/dist/{chunk-GXXLJHQX.js.map → chunk-7I2QMUEZ.js.map} +0 -0
  285. /package/dist/{chunk-NYOQNYSI.js.map → chunk-AW3LVWVV.js.map} +0 -0
  286. /package/dist/{chunk-25YYEVSE.js.map → chunk-DG7TX763.js.map} +0 -0
  287. /package/dist/{chunk-TZSPLSDU.js.map → chunk-GYEZV4GK.js.map} +0 -0
  288. /package/dist/{chunk-ABU37QSG.js.map → chunk-MMF6HJB7.js.map} +0 -0
  289. /package/dist/{chunk-3L44PPMF.js.map → chunk-RPAOSHBN.js.map} +0 -0
@@ -1,255 +0,0 @@
1
- /**
2
- * Utilities for parsing NATS chunks into structured actions
3
- */
4
-
5
- import { MESSAGE_TYPE, type ChunkData, type ParsedChunkAction, type ToolExecutionSegment, type PendingToolCallData } from '../types'
6
-
7
- function normalizeToolCalls(raw: unknown): PendingToolCallData[] {
8
- if (!Array.isArray(raw)) return []
9
- return raw
10
- .filter((item): item is Record<string, any> => !!item && typeof item === 'object')
11
- .map((item) => ({
12
- toolExecutionRequestId: String(item.toolExecutionRequestId ?? ''),
13
- toolName: String(item.toolName ?? ''),
14
- toolTitle: typeof item.toolTitle === 'string' ? item.toolTitle : undefined,
15
- toolExplanation: typeof item.toolExplanation === 'string' ? item.toolExplanation : undefined,
16
- toolType: typeof item.toolType === 'string' ? item.toolType : undefined,
17
- requiresApproval: item.requiresApproval === true,
18
- approvalType: typeof item.approvalType === 'string' ? item.approvalType : null,
19
- toolCallArguments:
20
- item.toolCallArguments && typeof item.toolCallArguments === 'object'
21
- ? (item.toolCallArguments as Record<string, any>)
22
- : null,
23
- }))
24
- }
25
-
26
- /**
27
- * Parse a raw NATS chunk into a structured action
28
- */
29
- export function parseChunkToAction(chunk: unknown): ParsedChunkAction | null {
30
- if (!chunk || typeof chunk !== 'object') return null
31
-
32
- const data = chunk as ChunkData
33
- const type = String(data.type || '')
34
-
35
- switch (type) {
36
- case MESSAGE_TYPE.MESSAGE_START:
37
- return { action: 'message_start' }
38
-
39
- case MESSAGE_TYPE.MESSAGE_END:
40
- return { action: 'message_end' }
41
-
42
- case MESSAGE_TYPE.AI_METADATA: {
43
- const providerName = data.providerName || data.provider
44
- if (typeof data.modelName === 'string' && typeof providerName === 'string') {
45
- return {
46
- action: 'metadata',
47
- modelDisplayName: data.modelDisplayName,
48
- modelName: data.modelName,
49
- providerName,
50
- contextWindow: typeof data.contextWindow === 'number' ? data.contextWindow : 0,
51
- }
52
- }
53
- return null
54
- }
55
-
56
- case MESSAGE_TYPE.TEXT:
57
- if (typeof data.text === 'string') {
58
- return { action: 'text', text: data.text }
59
- }
60
- return null
61
-
62
- case MESSAGE_TYPE.THINKING:
63
- if (typeof data.text === 'string') {
64
- return { action: 'thinking', text: data.text }
65
- }
66
- return null
67
-
68
- case MESSAGE_TYPE.EXECUTING_TOOL:
69
- return {
70
- action: 'tool_execution',
71
- segment: {
72
- type: 'tool_execution',
73
- data: {
74
- type: 'EXECUTING_TOOL',
75
- integratedToolType: data.integratedToolType || '',
76
- toolFunction: data.toolFunction || '',
77
- toolTitle: typeof data.title === 'string' ? data.title : undefined,
78
- parameters: data.parameters,
79
- toolExecutionRequestId: typeof data.toolExecutionRequestId === 'string' ? data.toolExecutionRequestId : undefined,
80
- }
81
- }
82
- }
83
-
84
- case MESSAGE_TYPE.EXECUTED_TOOL:
85
- return {
86
- action: 'tool_execution',
87
- segment: {
88
- type: 'tool_execution',
89
- data: {
90
- type: 'EXECUTED_TOOL',
91
- integratedToolType: data.integratedToolType || '',
92
- toolFunction: data.toolFunction || '',
93
- toolTitle: typeof data.title === 'string' ? data.title : undefined,
94
- parameters: data.parameters,
95
- result: data.result,
96
- success: data.success,
97
- toolExecutionRequestId: typeof data.toolExecutionRequestId === 'string' ? data.toolExecutionRequestId : undefined,
98
- }
99
- }
100
- }
101
-
102
- case MESSAGE_TYPE.APPROVAL_REQUEST: {
103
- const requestId = data.approvalRequestId || data.approval_request_id || ''
104
- const approvalType = data.approvalType || 'USER'
105
- const toolCalls = normalizeToolCalls(data.toolCalls)
106
-
107
- if (toolCalls.length > 0) {
108
- return {
109
- action: 'approval_batch',
110
- requestId,
111
- approvalType,
112
- toolCalls,
113
- }
114
- }
115
-
116
- return {
117
- action: 'approval_request',
118
- requestId,
119
- command: data.command || '',
120
- explanation: data.explanation,
121
- approvalType,
122
- }
123
- }
124
-
125
- case MESSAGE_TYPE.APPROVAL_RESULT: {
126
- // The realtime NATS chunk carries the resolver's name as `displayName`; the
127
- // persisted GraphQL message exposes the same value as `resolvedByName`. Accept
128
- // either so realtime and history-replay render "by {name}" identically.
129
- const resolvedByName =
130
- typeof data.resolvedByName === 'string'
131
- ? data.resolvedByName
132
- : typeof data.displayName === 'string'
133
- ? data.displayName
134
- : undefined
135
- return {
136
- action: 'approval_result',
137
- requestId: data.approvalRequestId || data.approval_request_id || '',
138
- approved: data.approved === true,
139
- approvalType: data.approvalType || 'CLIENT',
140
- resolvedByName,
141
- }
142
- }
143
-
144
- case MESSAGE_TYPE.ERROR:
145
- return {
146
- action: 'error',
147
- error: data.error || 'An error occurred',
148
- details: data.details,
149
- }
150
-
151
- case MESSAGE_TYPE.MESSAGE_REQUEST:
152
- return {
153
- action: 'message_request',
154
- text: String(data.text || ''),
155
- ownerType: typeof data.ownerType === 'string' ? data.ownerType : undefined,
156
- displayName: typeof data.displayName === 'string' ? data.displayName : undefined,
157
- userId: typeof data.userId === 'string' ? data.userId : undefined,
158
- // Entity-context refs the user attached to this message (backend
159
- // `MESSAGE_REQUEST` chunk → `contextItems: [{ type, id }]`). The wire
160
- // shape carries no label; the host resolves display text + icon. `label`
161
- // is REQUIRED on `ChatContextItem`, so fall back to the id (same as the
162
- // historical path in `process-historical-messages.ts`) — keeps both
163
- // message sources producing an identical shape.
164
- contextItems: Array.isArray(data.contextItems)
165
- ? (data.contextItems as Array<{ type?: unknown; id?: unknown }>)
166
- .filter((it) => typeof it?.type === 'string' && typeof it?.id === 'string')
167
- .map((it) => ({ type: it.type as string, id: it.id as string, label: it.id as string }))
168
- : undefined,
169
- }
170
-
171
- case MESSAGE_TYPE.TOKEN_USAGE:
172
- return {
173
- action: 'token_usage',
174
- data: {
175
- inputTokensSize: data.inputTokensSize ?? 0,
176
- outputTokensSize: data.outputTokensSize ?? 0,
177
- totalTokensSize: data.totalTokensSize ?? 0,
178
- contextSize: data.contextSize ?? 0,
179
- },
180
- }
181
-
182
- case MESSAGE_TYPE.CONTEXT_COMPACTION_START:
183
- return { action: 'context_compaction_start' }
184
-
185
- case MESSAGE_TYPE.CONTEXT_COMPACTION_END:
186
- return {
187
- action: 'context_compaction_end',
188
- summary: typeof data.text === 'string' ? data.text : undefined,
189
- }
190
-
191
- case MESSAGE_TYPE.SYSTEM:
192
- if (typeof data.text === 'string') {
193
- return { action: 'system', text: data.text }
194
- }
195
- return null
196
-
197
- case MESSAGE_TYPE.DIRECT_MESSAGE:
198
- if (typeof data.text === 'string') {
199
- return {
200
- action: 'direct_message',
201
- text: data.text,
202
- ownerType: typeof data.ownerType === 'string' ? data.ownerType : undefined,
203
- displayName: typeof data.displayName === 'string' ? data.displayName : undefined,
204
- userId: typeof data.userId === 'string' ? data.userId : undefined,
205
- }
206
- }
207
- return null
208
-
209
- case MESSAGE_TYPE.DIALOG_CLOSED:
210
- return { action: 'dialog_closed' }
211
-
212
- default:
213
- return null
214
- }
215
- }
216
-
217
- /**
218
- * Check if a chunk represents a control message (start/end)
219
- */
220
- export function isControlChunk(chunk: unknown): boolean {
221
- if (!chunk || typeof chunk !== 'object') return false
222
- const data = chunk as ChunkData
223
- const type = String(data.type || '')
224
- return type === MESSAGE_TYPE.MESSAGE_START || type === MESSAGE_TYPE.MESSAGE_END
225
- }
226
-
227
- /**
228
- * Check if a chunk represents an error
229
- */
230
- export function isErrorChunk(chunk: unknown): boolean {
231
- if (!chunk || typeof chunk !== 'object') return false
232
- const data = chunk as ChunkData
233
- return data.type === MESSAGE_TYPE.ERROR
234
- }
235
-
236
- /**
237
- * Check if a chunk represents metadata
238
- */
239
- export function isMetadataChunk(chunk: unknown): boolean {
240
- if (!chunk || typeof chunk !== 'object') return false
241
- const data = chunk as ChunkData
242
- return data.type === MESSAGE_TYPE.AI_METADATA
243
- }
244
-
245
- /**
246
- * Extract text content from a chunk if it's a text chunk
247
- */
248
- export function extractTextFromChunk(chunk: unknown): string | null {
249
- if (!chunk || typeof chunk !== 'object') return null
250
- const data = chunk as ChunkData
251
- if (data.type === MESSAGE_TYPE.TEXT && typeof data.text === 'string') {
252
- return data.text
253
- }
254
- return null
255
- }
@@ -1,40 +0,0 @@
1
- <!-- source-hash: cb258dc120396ef8c715487b0cdc1022 -->
2
- Client-side React component that renders LLM-generated markdown safely, combining `react-markdown` with a custom XSS sanitization pipeline and support for GitHub-flavored markdown, syntax highlighting, and embedded media.
3
-
4
- ## Key Components
5
-
6
- ### Security Pipeline
7
- - **`rehypeStripUnsafe()`** — Custom rehype plugin that strips dangerous HAST nodes after `rehype-raw` parsing. Removes `<script>`, `<style>`, `<object>`, event handler attributes (`on*`), `javascript:` / `data:` URIs, and `iframe srcdoc` vectors.
8
- - **`srcsetHasUnsafeCandidate()`** — Inspects every candidate URL in `srcset` attributes (not just the first), preventing multi-candidate injection attacks.
9
- - **`escapeUnknownHtmlTags()`** — Pre-processes markdown text to escape HTML tags not in the `SAFE_HTML_TAGS` allowlist, preventing LLM-emitted XML-style tags (e.g., `<ticket>`, `<their>`) from reaching React as unrecognized custom elements. Preserves code blocks and inline code spans.
10
- - **`cardAwareUrlTransform()`** — Extends `react-markdown`'s default URL sanitizer to allow the internal `card://` scheme for chat-card markers while keeping all other unsafe schemes blocked.
11
-
12
- ### Constants & Regexes
13
- | Export | Purpose |
14
- |--------|---------|
15
- | `SAFE_HTML_TAGS` | Allowlist of permitted HTML5 tags forwarded to React |
16
- | `STRIP_ELEMENTS` | Tags removed entirely at the HAST level |
17
- | `EVENT_HANDLER_ATTR_RE` | Matches `on*` attribute names |
18
- | `JAVASCRIPT_URL_RE` / `DATA_URL_RE` | Detect unsafe URL schemes |
19
- | `TAG_LIKE_REGEX` | Parses HTML-like tags in markdown source |
20
-
21
- ### Mermaid Support
22
- - `mermaidStyles` — Responsive CSS for Mermaid SVG diagrams using DM Sans font.
23
-
24
- ## Usage Example
25
-
26
- ```typescript
27
- import { SimpleMarkdownRenderer } from './simple-markdown-renderer';
28
-
29
- // Basic usage — content is sanitized automatically
30
- <SimpleMarkdownRenderer
31
- content="## Hello\n\nThis is **LLM-generated** markdown with `code`."
32
- />
33
-
34
- // The sanitizer prevents XSS from LLM output automatically:
35
- // "<script>alert(1)</script>" → stripped
36
- // "<their> tag" → escaped to &lt;their&gt;
37
- // "javascript:alert(1)" href → removed
38
- ```
39
-
40
- > **Note:** This renderer is designed specifically for untrusted LLM output. The sanitization pipeline runs in layers: text pre-processing → `rehype-raw` → `rehypeStripUnsafe` → `rehype-highlight`, ensuring no XSS vectors survive even if one layer is bypassed. Community support is available on the [OpenMSP Slack](https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA).