@flamingo-stack/openframe-frontend-core 0.0.508 → 0.0.509

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 (306) 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 +216 -0
  8. package/dist/chat-protocol/events.d.ts.map +1 -0
  9. package/dist/chat-protocol/frames.d.ts +213 -0
  10. package/dist/chat-protocol/frames.d.ts.map +1 -0
  11. package/dist/chat-protocol/index.cjs +506 -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 +490 -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-3SQ5KXHQ.cjs → chunk-2T4GTV25.cjs} +9 -9
  22. package/dist/{chunk-3SQ5KXHQ.cjs.map → chunk-2T4GTV25.cjs.map} +1 -1
  23. package/dist/{chunk-CWAOV2FK.cjs → chunk-3CGZPAGR.cjs} +3 -3
  24. package/dist/{chunk-CWAOV2FK.cjs.map → chunk-3CGZPAGR.cjs.map} +1 -1
  25. package/dist/{chunk-TLMJHMXJ.js → chunk-3QSR22IC.js} +12 -12
  26. package/dist/chunk-3QSR22IC.js.map +1 -0
  27. package/dist/{chunk-TWYNR4TZ.cjs → chunk-4G5TLHJD.cjs} +7141 -4799
  28. package/dist/chunk-4G5TLHJD.cjs.map +1 -0
  29. package/dist/{chunk-ADPMHWOE.js → chunk-72XAID7Y.js} +4 -4
  30. package/dist/{chunk-PAGKRNWK.js → chunk-7WZHBQ4J.js} +2 -2
  31. package/dist/{chunk-OCEKO5CW.js → chunk-AEELJC4N.js} +12106 -9764
  32. package/dist/chunk-AEELJC4N.js.map +1 -0
  33. package/dist/{chunk-Z42BGM6Q.cjs → chunk-BT2WWDFP.cjs} +5 -5
  34. package/dist/{chunk-Z42BGM6Q.cjs.map → chunk-BT2WWDFP.cjs.map} +1 -1
  35. package/dist/{chunk-7LEL3RIX.cjs → chunk-C7OY3PQP.cjs} +11 -11
  36. package/dist/{chunk-7LEL3RIX.cjs.map → chunk-C7OY3PQP.cjs.map} +1 -1
  37. package/dist/{chunk-RHGGEKPQ.cjs → chunk-CIOLOQKQ.cjs} +4 -4
  38. package/dist/{chunk-RHGGEKPQ.cjs.map → chunk-CIOLOQKQ.cjs.map} +1 -1
  39. package/dist/{chunk-TSZHM74B.js → chunk-DC2TKS7C.js} +2 -2
  40. package/dist/{chunk-M2GOR3XQ.cjs → chunk-DYPYR7FR.cjs} +87 -87
  41. package/dist/{chunk-M2GOR3XQ.cjs.map → chunk-DYPYR7FR.cjs.map} +1 -1
  42. package/dist/{chunk-I64ABCDX.js → chunk-I2B6X77L.js} +2 -2
  43. package/dist/{chunk-NIZDKTGL.cjs → chunk-K5MSCMDK.cjs} +37 -37
  44. package/dist/{chunk-NIZDKTGL.cjs.map → chunk-K5MSCMDK.cjs.map} +1 -1
  45. package/dist/{chunk-DTYRYB2N.js → chunk-K6QTZ7CZ.js} +2 -2
  46. package/dist/{chunk-4LTMXDUS.js → chunk-KBN7PMFT.js} +2 -2
  47. package/dist/{chunk-TBMV7I5N.js → chunk-KXZO2WZX.js} +2 -2
  48. package/dist/{chunk-QTYZMP6D.cjs → chunk-LBAKLT6T.cjs} +62 -62
  49. package/dist/chunk-LBAKLT6T.cjs.map +1 -0
  50. package/dist/{chunk-KEBYLU3U.js → chunk-LFUPI7VX.js} +2 -2
  51. package/dist/{chunk-LDTR4IVZ.cjs → chunk-M37PBG4N.cjs} +31 -31
  52. package/dist/{chunk-LDTR4IVZ.cjs.map → chunk-M37PBG4N.cjs.map} +1 -1
  53. package/dist/{chunk-WA7RR64F.js → chunk-PO5O654H.js} +6 -5
  54. package/dist/chunk-PO5O654H.js.map +1 -0
  55. package/dist/{chunk-WK4N5VBX.cjs → chunk-QJJISLPA.cjs} +28 -27
  56. package/dist/chunk-QJJISLPA.cjs.map +1 -0
  57. package/dist/{chunk-2F44PLTV.cjs → chunk-T7MCSA55.cjs} +26 -26
  58. package/dist/{chunk-2F44PLTV.cjs.map → chunk-T7MCSA55.cjs.map} +1 -1
  59. package/dist/{chunk-WJQHJD7J.js → chunk-TWSKTJHW.js} +2 -2
  60. package/dist/{chunk-ZSQHZYCO.cjs → chunk-UQDMJ6DH.cjs} +13 -13
  61. package/dist/{chunk-ZSQHZYCO.cjs.map → chunk-UQDMJ6DH.cjs.map} +1 -1
  62. package/dist/{chunk-TZRUCD56.js → chunk-V3ZAAFE3.js} +5 -5
  63. package/dist/{chunk-LRGHJPET.js → chunk-XGIFOHKE.js} +2 -2
  64. package/dist/{chunk-POOMO3PA.cjs → chunk-YQEPRYT5.cjs} +7 -7
  65. package/dist/{chunk-POOMO3PA.cjs.map → chunk-YQEPRYT5.cjs.map} +1 -1
  66. package/dist/components/case-studies/index.cjs +8 -8
  67. package/dist/components/case-studies/index.js +2 -2
  68. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  69. package/dist/components/chat/chat-message-list.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-chunk-catchup.d.ts.map +1 -1
  74. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +15 -48
  75. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
  76. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +10 -57
  77. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
  78. package/dist/components/chat/index.cjs +10 -2
  79. package/dist/components/chat/index.cjs.map +1 -1
  80. package/dist/components/chat/index.d.ts +1 -0
  81. package/dist/components/chat/index.d.ts.map +1 -1
  82. package/dist/components/chat/index.js +21 -13
  83. package/dist/components/chat/stream/chat-dialog-store.d.ts +184 -0
  84. package/dist/components/chat/stream/chat-dialog-store.d.ts.map +1 -0
  85. package/dist/components/chat/stream/chat-stream-reducer.d.ts +380 -0
  86. package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +1 -0
  87. package/dist/components/chat/stream/delta-batcher.d.ts +51 -0
  88. package/dist/components/chat/stream/delta-batcher.d.ts.map +1 -0
  89. package/dist/components/chat/stream/index.d.ts +17 -0
  90. package/dist/components/chat/stream/index.d.ts.map +1 -0
  91. package/dist/components/chat/stream/message-mutations.d.ts +77 -0
  92. package/dist/components/chat/stream/message-mutations.d.ts.map +1 -0
  93. package/dist/components/chat/stream/use-chat-stream-reducer.d.ts +22 -0
  94. package/dist/components/chat/stream/use-chat-stream-reducer.d.ts.map +1 -0
  95. package/dist/components/chat/types/api.types.d.ts +1 -81
  96. package/dist/components/chat/types/api.types.d.ts.map +1 -1
  97. package/dist/components/chat/types/processing.types.d.ts +2 -93
  98. package/dist/components/chat/types/processing.types.d.ts.map +1 -1
  99. package/dist/components/chat/types/unified-chat-state.types.d.ts +15 -0
  100. package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
  101. package/dist/components/chat/utils/extract-incomplete-message-state.d.ts +34 -6
  102. package/dist/components/chat/utils/extract-incomplete-message-state.d.ts.map +1 -1
  103. package/dist/components/chat/utils/history-merge.d.ts.map +1 -1
  104. package/dist/components/chat/utils/index.d.ts +2 -3
  105. package/dist/components/chat/utils/index.d.ts.map +1 -1
  106. package/dist/components/chat/utils/process-historical-messages.d.ts +59 -11
  107. package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
  108. package/dist/components/contact/index.cjs +3 -3
  109. package/dist/components/contact/index.js +2 -2
  110. package/dist/components/docs/index.cjs +5 -5
  111. package/dist/components/docs/index.js +4 -4
  112. package/dist/components/embeds/index.cjs +3 -3
  113. package/dist/components/embeds/index.js +2 -2
  114. package/dist/components/faq/index.cjs +3 -3
  115. package/dist/components/faq/index.js +2 -2
  116. package/dist/components/features/index.cjs +2 -2
  117. package/dist/components/features/index.js +1 -1
  118. package/dist/components/help-center-pages/index.cjs +22 -22
  119. package/dist/components/help-center-pages/index.js +13 -13
  120. package/dist/components/index.cjs +174 -132
  121. package/dist/components/index.cjs.map +1 -1
  122. package/dist/components/index.js +65 -23
  123. package/dist/components/index.js.map +1 -1
  124. package/dist/components/meeting-scheduler/index.cjs +34 -34
  125. package/dist/components/meeting-scheduler/index.js +3 -3
  126. package/dist/components/navigation/index.cjs +2 -2
  127. package/dist/components/navigation/index.js +1 -1
  128. package/dist/components/onboarding-guides/index.cjs +5 -5
  129. package/dist/components/onboarding-guides/index.js +4 -4
  130. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
  131. package/dist/components/related-content/index.cjs +3 -3
  132. package/dist/components/related-content/index.js +2 -2
  133. package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
  134. package/dist/components/tickets/index.cjs +6 -6
  135. package/dist/components/tickets/index.js +5 -5
  136. package/dist/components/ui/index.cjs +44 -2
  137. package/dist/components/ui/index.cjs.map +1 -1
  138. package/dist/components/ui/index.d.ts +1 -2
  139. package/dist/components/ui/index.d.ts.map +1 -1
  140. package/dist/components/ui/index.js +55 -13
  141. package/dist/components/ui/markdown/base-components.d.ts +51 -0
  142. package/dist/components/ui/markdown/base-components.d.ts.map +1 -0
  143. package/dist/components/ui/markdown/engine.d.ts +99 -0
  144. package/dist/components/ui/markdown/engine.d.ts.map +1 -0
  145. package/dist/components/ui/markdown/heading-ids.d.ts +65 -0
  146. package/dist/components/ui/markdown/heading-ids.d.ts.map +1 -0
  147. package/dist/components/ui/markdown/index.d.ts +18 -0
  148. package/dist/components/ui/markdown/index.d.ts.map +1 -0
  149. package/dist/components/ui/markdown/mermaid-diagram.d.ts +79 -0
  150. package/dist/components/ui/markdown/mermaid-diagram.d.ts.map +1 -0
  151. package/dist/components/ui/markdown/rich/embed-overrides.d.ts +14 -0
  152. package/dist/components/ui/markdown/rich/embed-overrides.d.ts.map +1 -0
  153. package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts +40 -0
  154. package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts.map +1 -0
  155. package/dist/components/ui/markdown/rich/shortcodes.d.ts +8 -0
  156. package/dist/components/ui/markdown/rich/shortcodes.d.ts.map +1 -0
  157. package/dist/components/ui/markdown/sanitize.d.ts +153 -0
  158. package/dist/components/ui/markdown/sanitize.d.ts.map +1 -0
  159. package/dist/components/ui/markdown/simple-markdown-renderer.d.ts +23 -0
  160. package/dist/components/ui/markdown/simple-markdown-renderer.d.ts.map +1 -0
  161. package/dist/components/ui/markdown/streaming.d.ts +78 -0
  162. package/dist/components/ui/markdown/streaming.d.ts.map +1 -0
  163. package/dist/components/ui/markdown/text-size.d.ts +34 -0
  164. package/dist/components/ui/markdown/text-size.d.ts.map +1 -0
  165. package/dist/index.cjs +60 -2
  166. package/dist/index.cjs.map +1 -1
  167. package/dist/index.js +71 -13
  168. package/dist/utils/index.cjs +169 -40
  169. package/dist/utils/index.cjs.map +1 -1
  170. package/dist/utils/index.d.ts +1 -0
  171. package/dist/utils/index.d.ts.map +1 -1
  172. package/dist/utils/index.js +162 -41
  173. package/dist/utils/index.js.map +1 -1
  174. package/dist/utils/markdown-fences.d.ts +42 -0
  175. package/dist/utils/markdown-fences.d.ts.map +1 -0
  176. package/dist/utils/markdown-heading-id.d.ts +85 -0
  177. package/dist/utils/markdown-heading-id.d.ts.map +1 -0
  178. package/dist/utils/markdown-section-extractor.d.ts.map +1 -1
  179. package/package.json +7 -1
  180. package/src/chat-protocol/__tests__/__snapshots__/nats-decoder-golden.test.ts.snap +319 -0
  181. package/src/chat-protocol/__tests__/chat-protocol.test.ts +516 -0
  182. package/src/chat-protocol/__tests__/env-flag.test.ts +52 -0
  183. package/src/chat-protocol/__tests__/ip-normalize.test.ts +136 -0
  184. package/src/chat-protocol/__tests__/nats-decoder-golden.test.ts +237 -0
  185. package/src/chat-protocol/decode.ts +278 -0
  186. package/src/chat-protocol/encode.ts +71 -0
  187. package/src/chat-protocol/env-flag.ts +39 -0
  188. package/src/chat-protocol/events.ts +254 -0
  189. package/src/chat-protocol/frames.ts +245 -0
  190. package/src/chat-protocol/index.ts +21 -0
  191. package/src/chat-protocol/ip-normalize.ts +146 -0
  192. package/src/chat-protocol/nats-decoder.ts +264 -0
  193. package/src/components/chat/.chat-message-list.md +10 -6
  194. package/src/components/chat/__tests__/chat-message-list.test.tsx +450 -9
  195. package/src/components/chat/__tests__/chat-message-streaming-memo.test.tsx +207 -0
  196. package/src/components/chat/__tests__/chat-pending-turn.test.tsx +250 -0
  197. package/src/components/chat/chat-message-enhanced.tsx +122 -20
  198. package/src/components/chat/chat-message-list.tsx +515 -133
  199. package/src/components/chat/embeddable-chat.tsx +6 -0
  200. package/src/components/chat/hooks/.index.md +30 -33
  201. package/src/components/chat/hooks/.use-nats-chat-adapter.md +36 -55
  202. package/src/components/chat/hooks/__tests__/__snapshots__/conversation-id-persistence-golden.test.ts.snap +37 -0
  203. package/src/components/chat/hooks/__tests__/__snapshots__/sse-stream-golden.test.ts.snap +0 -0
  204. package/src/components/chat/hooks/__tests__/chunk-catchup-dialog-staleness.test.ts +92 -0
  205. package/src/components/chat/hooks/__tests__/conversation-id-persistence-golden.test.ts +438 -0
  206. package/src/components/chat/hooks/__tests__/sse-stream-golden.test.ts +318 -0
  207. package/src/components/chat/hooks/index.ts +0 -1
  208. package/src/components/chat/hooks/use-chat.ts +8 -0
  209. package/src/components/chat/hooks/use-chunk-catchup.ts +26 -1
  210. package/src/components/chat/hooks/use-nats-chat-adapter.ts +254 -825
  211. package/src/components/chat/hooks/use-sse-chat-adapter.ts +380 -684
  212. package/src/components/chat/index.ts +5 -0
  213. package/src/components/chat/stream/__tests__/__snapshots__/chat-stream-reducer-golden.test.ts.snap +944 -0
  214. package/src/components/chat/stream/__tests__/chat-dialog-store.test.ts +806 -0
  215. package/src/components/chat/stream/__tests__/chat-stream-reducer-golden.test.ts +467 -0
  216. package/src/components/chat/stream/__tests__/chat-stream-reducer.test.ts +1330 -0
  217. package/src/components/chat/stream/__tests__/delta-batcher.test.ts +255 -0
  218. package/src/components/chat/stream/__tests__/use-chat-stream-reducer.test.ts +105 -0
  219. package/src/components/chat/stream/chat-dialog-store.ts +536 -0
  220. package/src/components/chat/stream/chat-stream-reducer.ts +1928 -0
  221. package/src/components/chat/stream/delta-batcher.ts +168 -0
  222. package/src/components/chat/stream/index.ts +55 -0
  223. package/src/components/chat/stream/message-mutations.ts +340 -0
  224. package/src/components/chat/stream/use-chat-stream-reducer.ts +126 -0
  225. package/src/components/chat/thinking-display.tsx +1 -1
  226. package/src/components/chat/types/.api.types.md +39 -49
  227. package/src/components/chat/types/.processing.types.md +29 -58
  228. package/src/components/chat/types/.unified-chat-state.types.md +2 -2
  229. package/src/components/chat/types/api.types.ts +6 -73
  230. package/src/components/chat/types/processing.types.ts +11 -53
  231. package/src/components/chat/types/unified-chat-state.types.ts +16 -0
  232. package/src/components/chat/utils/.extract-incomplete-message-state.md +21 -3
  233. package/src/components/chat/utils/.history-merge.md +44 -3
  234. package/src/components/chat/utils/.index.md +31 -40
  235. package/src/components/chat/utils/__tests__/__snapshots__/process-historical-messages-golden.test.ts.snap +420 -0
  236. package/src/components/chat/utils/__tests__/__snapshots__/segment-accumulator-golden.test.ts.snap +605 -0
  237. package/src/components/chat/utils/__tests__/extract-incomplete-message-state.test.ts +106 -0
  238. package/src/components/chat/utils/__tests__/history-merge.test.ts +160 -0
  239. package/src/components/chat/utils/__tests__/process-historical-messages-approvals.test.ts +61 -0
  240. package/src/components/chat/utils/__tests__/process-historical-messages-golden.test.ts +394 -0
  241. package/src/components/chat/utils/__tests__/segment-accumulator-golden.test.ts +270 -0
  242. package/src/components/chat/utils/extract-incomplete-message-state.ts +93 -6
  243. package/src/components/chat/utils/history-merge.ts +85 -5
  244. package/src/components/chat/utils/index.ts +5 -8
  245. package/src/components/chat/utils/process-historical-messages.ts +361 -385
  246. package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +22 -4
  247. package/src/components/shared/legal-document/legal-document-page.tsx +1 -1
  248. package/src/components/shared/product-release/release-detail-page.tsx +19 -4
  249. package/src/components/ui/__tests__/__snapshots__/markdown-parity.test.tsx.snap +2420 -0
  250. package/src/components/ui/__tests__/markdown-parity.test.tsx +2540 -0
  251. package/src/components/ui/index.ts +1 -2
  252. package/src/components/ui/markdown/__tests__/mermaid-security.test.ts +176 -0
  253. package/src/components/ui/markdown/__tests__/mermaid-stale-render.test.tsx +151 -0
  254. package/src/components/ui/markdown/__tests__/sanitize-invariant.test.ts +354 -0
  255. package/src/components/ui/markdown/__tests__/sanitize-render.test.tsx +118 -0
  256. package/src/components/ui/markdown/__tests__/streaming.test.tsx +436 -0
  257. package/src/components/ui/markdown/base-components.tsx +360 -0
  258. package/src/components/ui/markdown/engine.tsx +315 -0
  259. package/src/components/ui/markdown/heading-ids.ts +239 -0
  260. package/src/components/ui/markdown/index.ts +49 -0
  261. package/src/components/ui/markdown/mermaid-diagram.tsx +323 -0
  262. package/src/components/ui/markdown/rich/embed-overrides.tsx +199 -0
  263. package/src/components/ui/markdown/rich/rich-markdown-renderer.tsx +184 -0
  264. package/src/components/ui/markdown/rich/shortcodes.ts +170 -0
  265. package/src/components/ui/markdown/sanitize.ts +3584 -0
  266. package/src/components/ui/markdown/simple-markdown-renderer.tsx +28 -0
  267. package/src/components/ui/markdown/streaming.ts +390 -0
  268. package/src/components/ui/markdown/text-size.ts +106 -0
  269. package/src/components/ui/release-changelog-section.tsx +1 -1
  270. package/src/components/ui/ticket-info-section.tsx +1 -1
  271. package/src/utils/index.ts +1 -0
  272. package/src/utils/markdown-fences.ts +127 -0
  273. package/src/utils/markdown-heading-id.ts +348 -0
  274. package/src/utils/markdown-section-extractor.ts +41 -56
  275. package/dist/chunk-OCEKO5CW.js.map +0 -1
  276. package/dist/chunk-QTYZMP6D.cjs.map +0 -1
  277. package/dist/chunk-TLMJHMXJ.js.map +0 -1
  278. package/dist/chunk-TWYNR4TZ.cjs.map +0 -1
  279. package/dist/chunk-WA7RR64F.js.map +0 -1
  280. package/dist/chunk-WK4N5VBX.cjs.map +0 -1
  281. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts +0 -6
  282. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +0 -1
  283. package/dist/components/chat/utils/chunk-parser.d.ts +0 -25
  284. package/dist/components/chat/utils/chunk-parser.d.ts.map +0 -1
  285. package/dist/components/ui/rich-markdown-renderer.d.ts +0 -34
  286. package/dist/components/ui/rich-markdown-renderer.d.ts.map +0 -1
  287. package/dist/components/ui/simple-markdown-renderer.d.ts +0 -73
  288. package/dist/components/ui/simple-markdown-renderer.d.ts.map +0 -1
  289. package/src/components/chat/hooks/.use-realtime-chunk-processor.md +0 -77
  290. package/src/components/chat/hooks/use-realtime-chunk-processor.ts +0 -489
  291. package/src/components/chat/utils/.chunk-parser.md +0 -62
  292. package/src/components/chat/utils/chunk-parser.ts +0 -262
  293. package/src/components/ui/.simple-markdown-renderer.md +0 -52
  294. package/src/components/ui/rich-markdown-renderer.tsx +0 -1223
  295. package/src/components/ui/simple-markdown-renderer.tsx +0 -964
  296. /package/dist/{chunk-ADPMHWOE.js.map → chunk-72XAID7Y.js.map} +0 -0
  297. /package/dist/{chunk-PAGKRNWK.js.map → chunk-7WZHBQ4J.js.map} +0 -0
  298. /package/dist/{chunk-TSZHM74B.js.map → chunk-DC2TKS7C.js.map} +0 -0
  299. /package/dist/{chunk-I64ABCDX.js.map → chunk-I2B6X77L.js.map} +0 -0
  300. /package/dist/{chunk-DTYRYB2N.js.map → chunk-K6QTZ7CZ.js.map} +0 -0
  301. /package/dist/{chunk-4LTMXDUS.js.map → chunk-KBN7PMFT.js.map} +0 -0
  302. /package/dist/{chunk-TBMV7I5N.js.map → chunk-KXZO2WZX.js.map} +0 -0
  303. /package/dist/{chunk-KEBYLU3U.js.map → chunk-LFUPI7VX.js.map} +0 -0
  304. /package/dist/{chunk-WJQHJD7J.js.map → chunk-TWSKTJHW.js.map} +0 -0
  305. /package/dist/{chunk-TZRUCD56.js.map → chunk-V3ZAAFE3.js.map} +0 -0
  306. /package/dist/{chunk-LRGHJPET.js.map → chunk-XGIFOHKE.js.map} +0 -0
@@ -178,7 +178,6 @@ export * from './ticket-attachments-list'
178
178
  export * from './ticket-note-card'
179
179
  export * from './ticket-notes-section'
180
180
  export * from './marquee-wall'
181
- export * from './simple-markdown-renderer'
182
- export { RichMarkdownRenderer, type RichMarkdownRendererProps } from './rich-markdown-renderer'
181
+ export * from './markdown'
183
182
  export * from './filter-pill-row'
184
183
 
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Mermaid renders MODEL-authored diagram source on the chat path, and the
3
+ * result is injected with `dangerouslySetInnerHTML`. This fixture pins the
4
+ * hardening in ../mermaid-diagram.tsx: a hostile node label must NOT survive
5
+ * as live HTML.
6
+ *
7
+ * The test drives `mermaid` with the SAME security knobs the component sets,
8
+ * by IMPORTING them: `MERMAID_SECURITY_OPTIONS` is the single source of truth
9
+ * and is spread into both `mermaid.initialize` calls. There are no literals
10
+ * here to drift from the component — flipping `securityLevel` to `'loose'` in
11
+ * the constant fails this suite (verified).
12
+ *
13
+ * `secure` is part of that constant: it is the allowlist of config keys a
14
+ * `%%{init}%%` directive inside the diagram SOURCE may not override. mermaid's
15
+ * default list omits `htmlLabels`, so untrusted source could otherwise
16
+ * re-enable HTML labels while `securityLevel` stayed locked.
17
+ *
18
+ * jsdom NOTE (recorded, not proven): before `htmlLabels` was added to `secure`,
19
+ * a `%%{init: {"htmlLabels": true}}%%` directive was observed to make
20
+ * `mermaid.render` never settle under jsdom (>60s, against a passing
21
+ * two-render control). That was NOT reproduced in a real browser and may be an
22
+ * artifact of jsdom having no layout — it is NOT a confirmed browser DoS. The
23
+ * component wraps its render in a timeout regardless.
24
+ */
25
+ import { beforeAll, describe, expect, it } from 'vitest'
26
+ import { MERMAID_SECURITY_OPTIONS } from '../mermaid-diagram'
27
+
28
+ // jsdom implements no SVG layout, and mermaid's dagre pass measures text.
29
+ // These stubs are only about making the renderer RUN; they do not touch the
30
+ // sanitization path under test.
31
+ function installSvgLayoutStubs(): void {
32
+ const proto = (globalThis as unknown as { SVGElement?: { prototype: Record<string, unknown> } }).SVGElement?.prototype
33
+ if (!proto) return
34
+ proto.getBBox = function getBBox() {
35
+ return { x: 0, y: 0, width: 100, height: 20 }
36
+ }
37
+ proto.getComputedTextLength = function getComputedTextLength() {
38
+ return 100
39
+ }
40
+ proto.getScreenCTM = function getScreenCTM() {
41
+ return { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0, inverse: () => ({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }) }
42
+ }
43
+ }
44
+
45
+ // Second tuple slot: text that MUST be present in the rendered output — a
46
+ // positive control proving the diagram was actually drawn, so the negative
47
+ // assertions below can't pass on empty output. Note the two payloads are
48
+ // neutralized differently: the `<img>` survives as ESCAPED label text, while
49
+ // the `<script>` is dropped outright, so its control is the sibling node.
50
+ const HOSTILE_LABELS: ReadonlyArray<readonly [chart: string, expectedText: string]> = [
51
+ ['graph TD\n A["<img src=x onerror=alert(1)>"] --> B["ok"]', '<img'],
52
+ ['graph TD\n A["<script>alert(1)</script>"] --> B["ok"]', 'ok'],
53
+ // A `%%{init}%%` directive trying to unlock the two knobs. Both keys are in
54
+ // `secure`, so the override is rejected and the payload stays escaped.
55
+ [
56
+ '%%{init:{"securityLevel":"loose"}}%%\ngraph TD\n A["<img src=x onerror=alert(1)>"] --> B["ok"]',
57
+ '<img',
58
+ ],
59
+ [
60
+ '%%{init:{"htmlLabels":true}}%%\ngraph TD\n A["<img src=x onerror=alert(1)>"] --> B["ok"]',
61
+ '<img',
62
+ ],
63
+ // YAML front-matter config — the other in-source config channel.
64
+ [
65
+ '---\nconfig:\n securityLevel: loose\n---\ngraph TD\n A["<img src=x onerror=alert(1)>"] --> B["ok"]',
66
+ '<img',
67
+ ],
68
+ // `click` interaction directive: disabled outright by 'strict'.
69
+ ['graph TD\n A["ok"] --> B["b"]\n click A "javascript:alert(1)"', 'ok'],
70
+ ]
71
+
72
+ /** Initialize with the COMPONENT's security options — imported, never
73
+ * re-typed — so the fixture cannot drift from the renderer. */
74
+ function initializeLikeComponent(mermaid: { initialize: (c: Record<string, unknown>) => void }): void {
75
+ mermaid.initialize({
76
+ startOnLoad: false,
77
+ theme: 'dark',
78
+ flowchart: { useMaxWidth: true },
79
+ ...MERMAID_SECURITY_OPTIONS,
80
+ })
81
+ }
82
+
83
+ describe('mermaid hostile-label hardening', () => {
84
+ beforeAll(() => {
85
+ installSvgLayoutStubs()
86
+ })
87
+
88
+ it.each(HOSTILE_LABELS)('does not emit live HTML for %j', async (chart, expectedText) => {
89
+ const { default: mermaid } = await import('mermaid')
90
+
91
+ initializeLikeComponent(mermaid)
92
+
93
+ const { svg } = await mermaid.render(`mermaid-security-${Math.random().toString(36).slice(2)}`, chart)
94
+
95
+ // No live element, and no event-handler attribute, anywhere in the output.
96
+ expect(svg).not.toMatch(/<img[\s>]/i)
97
+ expect(svg).not.toMatch(/<script[\s>]/i)
98
+ expect(svg).not.toMatch(/\son[a-z]+\s*=/i)
99
+ // `htmlLabels: false` means no HTML subtree is minted for labels at all.
100
+ expect(svg).not.toMatch(/<foreignObject/i)
101
+ // 'strict' drops `click` bindings, so no javascript: URL is ever emitted.
102
+ expect(svg).not.toMatch(/javascript:/i)
103
+
104
+ // And it stays inert once parsed as HTML: the hostile markup must appear
105
+ // as TEXT (escaped), never as an element node.
106
+ const host = document.createElement('div')
107
+ host.innerHTML = svg
108
+ expect(host.querySelector('img')).toBeNull()
109
+ expect(host.querySelector('script')).toBeNull()
110
+ const text = host.textContent ?? ''
111
+ expect(text).toContain(expectedText)
112
+ // The script payload never survives in any form.
113
+ expect(text).not.toContain('alert(1)')
114
+ })
115
+ })
116
+
117
+ /**
118
+ * CSS is the OTHER injection surface, and the HTML hardening above does not
119
+ * cover it. `themeCSS` is raw CSS that mermaid emits into a `<style>` inside
120
+ * the SVG the component hands to `dangerouslySetInnerHTML`, and mermaid's
121
+ * directive sanitizer does not defend it: it is an ordinary config key whose
122
+ * value only gets brace-balanced. Before `themeCSS` was added to `secure`,
123
+ * both payloads below reproduced against real mermaid 11.14.0 — the first
124
+ * emitted `#svgId{position:fixed;…;z-index:2147483647;}` (an opaque top-most
125
+ * viewport-filling overlay whose visible text the author writes in the node
126
+ * labels), the second emitted a document-global `@font-face` fetching from an
127
+ * attacker host, because at-rules escape the `#svgId` prefix entirely.
128
+ *
129
+ * Diagram source on the chat path is MODEL output, so this is reachable from
130
+ * untrusted input. These cases fail if `themeCSS` leaves `secure`.
131
+ */
132
+ const HOSTILE_THEME_CSS: ReadonlyArray<readonly [label: string, chart: string]> = [
133
+ [
134
+ 'viewport-overlay via bare declarations',
135
+ // The label is deliberately neutral: in the real attack it reads
136
+ // "Session expired, sign in at <attacker host>", but putting a hostname in
137
+ // the label would trip this suite's own `not.toContain('evil.example')`
138
+ // assertion on legitimate TEXT rather than on injected CSS.
139
+ '%%{init:{"themeCSS":"position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:2147483647;background:#fff"}}%%\ngraph TD\n A["Session expired. Sign in again."] --> B["ok"]',
140
+ ],
141
+ [
142
+ 'document-global at-rule escaping the #svgId scope',
143
+ '%%{init:{"themeCSS":"@font-face { font-family: e; src: url(https://evil.example/f.woff) }"}}%%\ngraph TD\n A["ok"] --> B["b"]',
144
+ ],
145
+ [
146
+ 'the YAML front-matter config channel',
147
+ '---\nconfig:\n themeCSS: "position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:2147483647"\n---\ngraph TD\n A["ok"] --> B["b"]',
148
+ ],
149
+ ]
150
+
151
+ describe('mermaid themeCSS hardening', () => {
152
+ beforeAll(() => {
153
+ installSvgLayoutStubs()
154
+ })
155
+
156
+ it.each(HOSTILE_THEME_CSS)('rejects a themeCSS override — %s', async (_label, chart) => {
157
+ const { default: mermaid } = await import('mermaid')
158
+
159
+ initializeLikeComponent(mermaid)
160
+
161
+ const { svg } = await mermaid.render(
162
+ `mermaid-themecss-${Math.random().toString(36).slice(2)}`,
163
+ chart,
164
+ )
165
+
166
+ expect(svg).not.toMatch(/position\s*:\s*fixed/i)
167
+ expect(svg).not.toContain('2147483647')
168
+ expect(svg).not.toMatch(/@font-face/i)
169
+ expect(svg).not.toContain('evil.example')
170
+ // Positive control: the diagram still rendered, so the assertions above
171
+ // cannot be passing on empty output.
172
+ const host = document.createElement('div')
173
+ host.innerHTML = svg
174
+ expect(host.textContent ?? '').toContain('ok')
175
+ })
176
+ })
@@ -0,0 +1,151 @@
1
+ /**
2
+ * MermaidDiagram's render effect re-runs on every `chart` change, and during
3
+ * STREAMING the chart text grows chunk by chunk — so several renders are in
4
+ * flight at once. Without a per-effect cancellation guard a slower EARLIER
5
+ * render can resolve last and overwrite the newer output (and, on the error
6
+ * path, paint an error for a chart that is no longer displayed).
7
+ *
8
+ * The 15s render timeout does not close this: it rejects the race, but does
9
+ * not abort the underlying `mermaid.render`, so the stale write is merely
10
+ * bounded, not prevented. These fixtures pin the guard.
11
+ *
12
+ * `mermaid` is mocked with a hand-settled deferred so resolution ORDER is
13
+ * under the test's control. (The real-mermaid security fixture lives in
14
+ * ./mermaid-security.test.ts and must stay unmocked, hence a separate file.)
15
+ */
16
+ import { render, act } from '@testing-library/react'
17
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
18
+
19
+ interface Deferred {
20
+ chart: string
21
+ resolve: (value: { svg: string }) => void
22
+ reject: (err: Error) => void
23
+ }
24
+
25
+ const renders: Deferred[] = []
26
+
27
+ vi.mock('mermaid', () => ({
28
+ default: {
29
+ initialize: vi.fn(),
30
+ render: vi.fn(
31
+ (_id: string, chart: string) =>
32
+ new Promise<{ svg: string }>((resolve, reject) => {
33
+ renders.push({ chart, resolve, reject })
34
+ }),
35
+ ),
36
+ },
37
+ }))
38
+
39
+ import { MermaidDiagram } from '../mermaid-diagram'
40
+
41
+ /**
42
+ * Let the mocked dynamic import + the resolved promise chain flush.
43
+ *
44
+ * MACROTASK-based and BOUNDED-POLLING on purpose. A fixed number of
45
+ * `await Promise.resolve()` turns is NOT a settle condition here: the component
46
+ * reaches `mermaid.render` through `mount effect → setMounted → re-render →
47
+ * effect → await import('mermaid')`, and how many microtask turns a dynamic
48
+ * import takes to resolve differs across Node/vitest releases. Three turns
49
+ * happened to be enough on Node 22 and are NOT on Node 25, where the second
50
+ * `mermaid.render` had not been called yet when the assertions ran — the suite
51
+ * failed with `renders.length === 1` (and, once the real module leaked in, with
52
+ * a genuine mermaid parse error). Poll for the condition instead of guessing a
53
+ * tick count.
54
+ */
55
+ const flushUntil = async (done: () => boolean, what: string) => {
56
+ for (let i = 0; i < 50; i++) {
57
+ await act(async () => {
58
+ await new Promise((resolve) => setTimeout(resolve, 0))
59
+ })
60
+ if (done()) return
61
+ }
62
+ throw new Error(`timed out waiting for ${what}`)
63
+ }
64
+
65
+ /** Settle pending state updates when there is no specific condition to await. */
66
+ const flush = async () => {
67
+ await act(async () => {
68
+ await new Promise((resolve) => setTimeout(resolve, 0))
69
+ })
70
+ }
71
+
72
+ /** Wait until `mermaid.render` has been called exactly `n` times. */
73
+ const flushRenders = (n: number) =>
74
+ flushUntil(() => renders.length >= n, `${n} mermaid.render call(s)`)
75
+
76
+ const svgOf = (container: HTMLElement) =>
77
+ container.querySelector('.mermaid-svg-container')?.innerHTML ?? ''
78
+
79
+ describe('MermaidDiagram stale-render guard', () => {
80
+ beforeEach(() => {
81
+ renders.length = 0
82
+ })
83
+
84
+ it('ignores an earlier render that resolves after a newer chart', async () => {
85
+ const view = render(<MermaidDiagram chart="graph TD\n A-->B" />)
86
+ await flushRenders(1)
87
+ view.rerender(<MermaidDiagram chart="graph TD\n A-->B\n B-->C" />)
88
+ await flushRenders(2)
89
+
90
+ // Newer render lands first, then the abandoned earlier one.
91
+ await act(async () => {
92
+ renders[1]!.resolve({ svg: '<svg id="new"></svg>' })
93
+ })
94
+ await act(async () => {
95
+ renders[0]!.resolve({ svg: '<svg id="stale"></svg>' })
96
+ })
97
+ await flush()
98
+
99
+ expect(svgOf(view.container)).toContain('id="new"')
100
+ expect(svgOf(view.container)).not.toContain('id="stale"')
101
+ })
102
+
103
+ it('ignores a late failure from an abandoned render', async () => {
104
+ const view = render(<MermaidDiagram chart="graph TD\n A-->B" />)
105
+ await flushRenders(1)
106
+ view.rerender(<MermaidDiagram chart="graph TD\n A-->B\n B-->C" />)
107
+ await flushRenders(2)
108
+
109
+ await act(async () => {
110
+ renders[1]!.resolve({ svg: '<svg id="new"></svg>' })
111
+ })
112
+ await act(async () => {
113
+ renders[0]!.reject(new Error('Diagram rendering timed out after 15000ms'))
114
+ })
115
+ await flush()
116
+
117
+ expect(view.container.textContent).not.toContain('Diagram Error')
118
+ expect(svgOf(view.container)).toContain('id="new"')
119
+ })
120
+
121
+ /**
122
+ * The error state must not be STICKY. This is the streaming hot path, not an
123
+ * exotic case: the chart text grows chunk by chunk, every intermediate
124
+ * prefix is an invalid diagram, and mermaid rejects each one. The render body
125
+ * evaluates `error` BEFORE `svg`, so an uncleared message keeps the "Diagram
126
+ * Error" card on screen for the component's whole lifetime — the finished
127
+ * diagram never appears even though its render succeeded.
128
+ */
129
+ it('recovers from a transient failure once a later render succeeds', async () => {
130
+ const view = render(<MermaidDiagram chart="graph TD" />)
131
+ await flushRenders(1)
132
+
133
+ // Partial chart → parse error, exactly what a mid-stream prefix produces.
134
+ await act(async () => {
135
+ renders[0]!.reject(new Error('Parse error on line 1'))
136
+ })
137
+ await flush()
138
+ expect(view.container.textContent).toContain('Diagram Error')
139
+
140
+ // The next delta completes the chart and renders cleanly.
141
+ view.rerender(<MermaidDiagram chart="graph TD\n A-->B" />)
142
+ await flushRenders(2)
143
+ await act(async () => {
144
+ renders[1]!.resolve({ svg: '<svg id="settled"></svg>' })
145
+ })
146
+ await flush()
147
+
148
+ expect(view.container.textContent).not.toContain('Diagram Error')
149
+ expect(svgOf(view.container)).toContain('id="settled"')
150
+ })
151
+ })