@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
@@ -0,0 +1,467 @@
1
+ /**
2
+ * GOLDEN CHARACTERIZATION TESTS — the NATS kernel of
3
+ * `createChatStreamReducer`, driven through `decodeNatsChunk`.
4
+ *
5
+ * Originally written against the `useRealtimeChunkProcessor` compat hook
6
+ * (Phase 0 of the chat unification). That wrapper was deleted once every
7
+ * consumer moved to the reducer; the behavioral spec it pinned is far too
8
+ * valuable to lose, so the suite was RETARGETED at the reducer itself. The
9
+ * recorded snapshots are byte-identical to the wrapper-era ones — the only
10
+ * thing that changed is who dispatches the effects.
11
+ *
12
+ * `dispatch()` below replicates the deleted wrapper's effect→callback
13
+ * forwarding verbatim (including the `segments-after-approval-result`
14
+ * conditional), so the logs remain a 1:1 record of the legacy
15
+ * `RealtimeChunkCallbacks` contract. Do NOT "fix" behaviors captured here.
16
+ */
17
+
18
+ import { describe, it, expect } from 'vitest'
19
+ import { decodeNatsChunk } from '../../../../chat-protocol/nats-decoder'
20
+ import {
21
+ createChatStreamReducer,
22
+ type ChatStreamReducer,
23
+ type InitializeExtras,
24
+ } from '../chat-stream-reducer'
25
+ import type { ChatApprovalStatus, RealtimeChunkCallbacks } from '../../types'
26
+
27
+ type EventLog = Array<Record<string, unknown>>
28
+
29
+ /** Build a full callback set that records every invocation into `log`. */
30
+ function makeRecordingCallbacks(log: EventLog): RealtimeChunkCallbacks {
31
+ return {
32
+ onStreamStart: () => log.push({ event: 'onStreamStart' }),
33
+ onStreamEnd: () => log.push({ event: 'onStreamEnd' }),
34
+ onMetadata: (metadata) => log.push({ event: 'onMetadata', metadata }),
35
+ onSegmentsUpdate: (segments, metadata) =>
36
+ log.push({ event: 'onSegmentsUpdate', segments, metadata }),
37
+ onError: (error, details) => log.push({ event: 'onError', error, details }),
38
+ onUserMessage: (text, metadata) => log.push({ event: 'onUserMessage', text, metadata }),
39
+ onTokenUsage: (data) => log.push({ event: 'onTokenUsage', data }),
40
+ onDirectMessage: (text, metadata) => log.push({ event: 'onDirectMessage', text, metadata }),
41
+ onSystemMessage: (text, metadata) => log.push({ event: 'onSystemMessage', text, metadata }),
42
+ // Block bodies, not concise ones: `log.push` returns a number, so a
43
+ // concise async arrow is `() => Promise<number>` and does not satisfy the
44
+ // declared `(requestId?: string) => void | Promise<void>`.
45
+ onApprove: async () => {
46
+ log.push({ event: 'onApprove' })
47
+ },
48
+ onReject: async () => {
49
+ log.push({ event: 'onReject' })
50
+ },
51
+ onEscalatedApproval: (requestId, data) =>
52
+ log.push({ event: 'onEscalatedApproval', requestId, data }),
53
+ onEscalatedApprovalResult: (requestId, approved, data) =>
54
+ log.push({ event: 'onEscalatedApprovalResult', requestId, approved, data }),
55
+ onApprovalResolved: (requestId, status, approvalType, resolvedByName) =>
56
+ log.push({ event: 'onApprovalResolved', requestId, status, approvalType, resolvedByName }),
57
+ onToolExecuted: (segment) => log.push({ event: 'onToolExecuted', segment }),
58
+ onAgentBusy: () => log.push({ event: 'onAgentBusy' }),
59
+ onDialogClosed: () => log.push({ event: 'onDialogClosed' }),
60
+ }
61
+ }
62
+
63
+ interface SetupOptions {
64
+ callbacks?: RealtimeChunkCallbacks
65
+ batchApprovalsEnabled?: boolean
66
+ displayApprovalTypes?: string[]
67
+ approvalStatuses?: Record<string, ChatApprovalStatus>
68
+ isDirectMode?: boolean
69
+ initialState?: InitializeExtras
70
+ }
71
+
72
+ function setup(options: SetupOptions = {}) {
73
+ const log: EventLog = []
74
+ const callbacks = options.callbacks ?? makeRecordingCallbacks(log)
75
+
76
+ const reducer: ChatStreamReducer = createChatStreamReducer({
77
+ transport: 'nats',
78
+ batchApprovalsEnabled: options.batchApprovalsEnabled,
79
+ displayApprovalTypes: options.displayApprovalTypes,
80
+ approvalStatuses: options.approvalStatuses,
81
+ isDirectMode: options.isDirectMode,
82
+ crossMessageToolRouting: !!callbacks.onToolExecuted,
83
+ callbacks: {
84
+ onApprove: (id) => callbacks.onApprove?.(id),
85
+ onReject: (id) => callbacks.onReject?.(id),
86
+ },
87
+ onEffect: ({ name, args }) => {
88
+ const cbs = callbacks as Record<string, ((...a: unknown[]) => void) | undefined>
89
+ // Legacy conditional: the cumulative post-APPROVAL_RESULT emit fires
90
+ // only when the consumer did NOT wire onApprovalResolved.
91
+ if (name === 'segments-after-approval-result') {
92
+ if (!cbs.onApprovalResolved) cbs.onSegmentsUpdate?.(...args)
93
+ return
94
+ }
95
+ cbs[name]?.(...args)
96
+ },
97
+ })
98
+
99
+ // The wrapper initialized from `initialState` in a mount effect.
100
+ if (options.initialState) reducer.initializeWithState(null, options.initialState)
101
+
102
+ const feed = (chunks: unknown[]) => {
103
+ for (const chunk of chunks) {
104
+ const event = decodeNatsChunk(chunk)
105
+ if (event) reducer.apply(event)
106
+ }
107
+ }
108
+ return { log, reducer, feed }
109
+ }
110
+
111
+ const EXECUTING = {
112
+ type: 'EXECUTING_TOOL',
113
+ integratedToolType: 'TACTICAL_RMM',
114
+ toolFunction: 'run_script',
115
+ title: 'Run cleanup script',
116
+ parameters: { script: 'cleanup.sh' },
117
+ toolExecutionRequestId: 'exec-1',
118
+ }
119
+ const EXECUTED = {
120
+ type: 'EXECUTED_TOOL',
121
+ integratedToolType: 'TACTICAL_RMM',
122
+ toolFunction: 'run_script',
123
+ result: 'Freed 2.3 GB',
124
+ success: true,
125
+ toolExecutionRequestId: 'exec-1',
126
+ }
127
+
128
+ describe('chat stream reducer — legacy chunk-processor golden event logs', () => {
129
+ it('normal turn: start → metadata → text ×3 → token usage → end', () => {
130
+ const { log, feed } = setup()
131
+ feed([
132
+ { type: 'MESSAGE_START' },
133
+ {
134
+ type: 'AI_METADATA',
135
+ modelDisplayName: 'Claude Sonnet',
136
+ modelName: 'claude-sonnet-x',
137
+ providerName: 'anthropic',
138
+ contextWindow: 200000,
139
+ },
140
+ { type: 'TEXT', text: 'Hello' },
141
+ { type: 'TEXT', text: ', ' },
142
+ { type: 'TEXT', text: 'world' },
143
+ {
144
+ type: 'TOKEN_USAGE',
145
+ inputTokensSize: 100,
146
+ outputTokensSize: 20,
147
+ totalTokensSize: 120,
148
+ contextSize: 180000,
149
+ },
150
+ { type: 'MESSAGE_END' },
151
+ ])
152
+ expect(log).toMatchSnapshot()
153
+ })
154
+
155
+ it('streamSeq on content chunks is threaded into onSegmentsUpdate metadata', () => {
156
+ const { log, feed } = setup()
157
+ feed([
158
+ { type: 'MESSAGE_START' },
159
+ { type: 'TEXT', text: 'seq-stamped', streamSeq: 7 },
160
+ { type: 'MESSAGE_END' },
161
+ ])
162
+ expect(log).toMatchSnapshot()
163
+ })
164
+
165
+ it('cold start (no MESSAGE_START ever): text emits CUMULATIVE segments (no append flag)', () => {
166
+ const { log, feed } = setup()
167
+ feed([
168
+ { type: 'TEXT', text: 'cold ' },
169
+ { type: 'TEXT', text: 'start' },
170
+ ])
171
+ expect(log).toMatchSnapshot()
172
+ })
173
+
174
+ it('post-MESSAGE_END continuation: text/thinking emit DELTA segments with append:true', () => {
175
+ const { log, feed } = setup()
176
+ feed([
177
+ { type: 'MESSAGE_START' },
178
+ { type: 'TEXT', text: 'in-stream' },
179
+ { type: 'MESSAGE_END' },
180
+ { type: 'TEXT', text: 'post-end text' },
181
+ { type: 'THINKING', text: 'post-end thinking' },
182
+ ])
183
+ expect(log).toMatchSnapshot()
184
+ })
185
+
186
+ it('tool execution OUTSIDE a message window: onAgentBusy + cross-message onToolExecuted (accumulator skipped)', () => {
187
+ const { log, feed } = setup()
188
+ // No MESSAGE_START — approved commands execute between the approval
189
+ // bubble's MESSAGE_END and the continuation stream.
190
+ feed([EXECUTING, EXECUTED])
191
+ expect(log).toMatchSnapshot()
192
+ })
193
+
194
+ it('tool execution IN-stream: accumulator-driven segment updates, onToolExecuted NOT fired', () => {
195
+ const { log, feed } = setup()
196
+ feed([
197
+ { type: 'MESSAGE_START' },
198
+ { type: 'TEXT', text: 'Running now. ' },
199
+ EXECUTING,
200
+ EXECUTED,
201
+ { type: 'MESSAGE_END' },
202
+ ])
203
+ expect(log).toMatchSnapshot()
204
+ })
205
+
206
+ it('approval request (displayed) → approval result: in-message flip + onApprovalResolved', () => {
207
+ const { log, feed } = setup()
208
+ feed([
209
+ { type: 'MESSAGE_START' },
210
+ {
211
+ type: 'APPROVAL_REQUEST',
212
+ approvalRequestId: 'req-1',
213
+ approvalType: 'CLIENT',
214
+ command: 'systemctl restart nats',
215
+ explanation: 'Restart the broker',
216
+ },
217
+ { type: 'MESSAGE_END' },
218
+ {
219
+ type: 'APPROVAL_RESULT',
220
+ approvalRequestId: 'req-1',
221
+ approved: true,
222
+ approvalType: 'CLIENT',
223
+ displayName: 'Jane Admin',
224
+ },
225
+ ])
226
+ // CHARACTERIZATION: because onApprovalResolved IS wired, the result
227
+ // does NOT emit onSegmentsUpdate — only the cross-message callback.
228
+ expect(log).toMatchSnapshot()
229
+ })
230
+
231
+ it('approval result WITHOUT onApprovalResolved wired: emits cumulative onSegmentsUpdate instead', () => {
232
+ const log: EventLog = []
233
+ const callbacks = makeRecordingCallbacks(log)
234
+ delete callbacks.onApprovalResolved
235
+ const { feed } = setup({ callbacks })
236
+ feed([
237
+ { type: 'MESSAGE_START' },
238
+ {
239
+ type: 'APPROVAL_REQUEST',
240
+ approvalRequestId: 'req-1',
241
+ approvalType: 'CLIENT',
242
+ command: 'reboot',
243
+ },
244
+ {
245
+ type: 'APPROVAL_RESULT',
246
+ approvalRequestId: 'req-1',
247
+ approved: false,
248
+ approvalType: 'CLIENT',
249
+ },
250
+ ])
251
+ expect(log).toMatchSnapshot()
252
+ })
253
+
254
+ it('escalated approval (type not displayed) → onEscalatedApproval, then result appends resolved card', () => {
255
+ const { log, feed, reducer } = setup() // displayApprovalTypes defaults to ['CLIENT']
256
+ feed([
257
+ { type: 'MESSAGE_START' },
258
+ {
259
+ type: 'APPROVAL_REQUEST',
260
+ approvalRequestId: 'req-adm',
261
+ approvalType: 'ADMIN',
262
+ command: 'drop database prod',
263
+ },
264
+ { type: 'MESSAGE_END' },
265
+ {
266
+ type: 'APPROVAL_RESULT',
267
+ approvalRequestId: 'req-adm',
268
+ approved: true,
269
+ approvalType: 'ADMIN',
270
+ },
271
+ ])
272
+ expect({
273
+ log,
274
+ pendingAfter: Array.from(reducer.getPendingEscalated().entries()),
275
+ }).toMatchSnapshot()
276
+ })
277
+
278
+ it('batch approval (batchApprovalsEnabled default ON): one batch segment, executions merge into it', () => {
279
+ const { log, feed } = setup()
280
+ feed([
281
+ { type: 'MESSAGE_START' },
282
+ {
283
+ type: 'APPROVAL_REQUEST',
284
+ approvalRequestId: 'batch-1',
285
+ approvalType: 'CLIENT',
286
+ toolCalls: [
287
+ {
288
+ toolExecutionRequestId: 'exec-a',
289
+ toolName: 'create_ticket',
290
+ toolTitle: 'Create ticket',
291
+ requiresApproval: true,
292
+ approvalType: 'CLIENT',
293
+ toolCallArguments: { subject: 'Printer down' },
294
+ },
295
+ {
296
+ toolExecutionRequestId: 'exec-b',
297
+ toolName: 'read_kb',
298
+ requiresApproval: false,
299
+ },
300
+ ],
301
+ },
302
+ {
303
+ type: 'APPROVAL_RESULT',
304
+ approvalRequestId: 'batch-1',
305
+ approved: true,
306
+ displayName: 'Alice Client',
307
+ },
308
+ {
309
+ type: 'EXECUTING_TOOL',
310
+ integratedToolType: 'PSA',
311
+ toolFunction: 'create_ticket',
312
+ toolExecutionRequestId: 'exec-a',
313
+ },
314
+ {
315
+ type: 'EXECUTED_TOOL',
316
+ integratedToolType: 'PSA',
317
+ toolFunction: 'create_ticket',
318
+ result: 'Ticket #77 created',
319
+ success: true,
320
+ toolExecutionRequestId: 'exec-a',
321
+ },
322
+ { type: 'MESSAGE_END' },
323
+ ])
324
+ expect(log).toMatchSnapshot()
325
+ })
326
+
327
+ it('batch approval with batchApprovalsEnabled:false unfolds into legacy cards (requiresApproval only)', () => {
328
+ const { log, feed } = setup({ batchApprovalsEnabled: false })
329
+ feed([
330
+ { type: 'MESSAGE_START' },
331
+ {
332
+ type: 'APPROVAL_REQUEST',
333
+ approvalRequestId: 'batch-1',
334
+ approvalType: 'CLIENT',
335
+ toolCalls: [
336
+ {
337
+ toolExecutionRequestId: 'exec-a',
338
+ toolName: 'create_ticket',
339
+ toolTitle: 'Create ticket',
340
+ requiresApproval: true,
341
+ toolCallArguments: { subject: 'Printer down' },
342
+ },
343
+ {
344
+ toolExecutionRequestId: 'exec-b',
345
+ toolName: 'read_kb',
346
+ requiresApproval: false,
347
+ },
348
+ ],
349
+ },
350
+ { type: 'MESSAGE_END' },
351
+ ])
352
+ expect(log).toMatchSnapshot()
353
+ })
354
+
355
+ it('CHARACTERIZATION duplicate/out-of-order: redelivered EXECUTING after EXECUTED in-stream appends a NEW executing segment (no dedup)', () => {
356
+ // The reducer does no duplicate suppression for standalone tool
357
+ // segments — dedup only exists inside approval batches (no-downgrade
358
+ // rule). Recording actual behavior, see unification plan.
359
+ const { log, feed } = setup()
360
+ feed([
361
+ { type: 'MESSAGE_START' },
362
+ EXECUTING,
363
+ EXECUTED,
364
+ EXECUTING, // redelivered
365
+ { type: 'MESSAGE_END' },
366
+ ])
367
+ expect(log).toMatchSnapshot()
368
+ })
369
+
370
+ it('error chunk: segment append + onError with JSON-extracted message', () => {
371
+ const { log, feed } = setup()
372
+ feed([
373
+ { type: 'MESSAGE_START' },
374
+ { type: 'TEXT', text: 'partial' },
375
+ { type: 'ERROR', error: 'Agent crashed', details: '{"error":{"message":"boom"}}' },
376
+ { type: 'ERROR', error: 'Plain details', details: 'not-json' },
377
+ ])
378
+ expect(log).toMatchSnapshot()
379
+ })
380
+
381
+ it('user echo / system / direct-message / dialog-closed routing', () => {
382
+ const { log, feed } = setup()
383
+ feed([
384
+ {
385
+ type: 'MESSAGE_REQUEST',
386
+ text: 'open a ticket',
387
+ ownerType: 'CLIENT',
388
+ displayName: 'Alice',
389
+ userId: 'user-42',
390
+ streamSeq: 3,
391
+ contextItems: [{ type: 'device', id: 'dev-1' }],
392
+ },
393
+ { type: 'SYSTEM', text: 'User joined the chat', streamSeq: 4 },
394
+ {
395
+ type: 'DIRECT_MESSAGE',
396
+ text: 'Human here now',
397
+ ownerType: 'ADMIN',
398
+ displayName: 'Jane Admin',
399
+ userId: 'admin-7',
400
+ streamSeq: 5,
401
+ },
402
+ { type: 'DIALOG_CLOSED' },
403
+ ])
404
+ expect(log).toMatchSnapshot()
405
+ })
406
+
407
+ it('direct-mode barrier: after a DIRECT_MESSAGE, AI chunks are dropped with a one-shot teardown', () => {
408
+ const { log, feed } = setup()
409
+ feed([
410
+ { type: 'MESSAGE_START' },
411
+ { type: 'TEXT', text: 'ai text before takeover' },
412
+ { type: 'DIRECT_MESSAGE', text: 'Human takeover', ownerType: 'ADMIN' },
413
+ // AI chunks now dropped; first one triggers the teardown (onStreamEnd).
414
+ { type: 'TEXT', text: 'dropped ai text' },
415
+ { type: 'TEXT', text: 'also dropped' },
416
+ // Allowlisted chunks still flow.
417
+ { type: 'SYSTEM', text: 'still visible' },
418
+ { type: 'DIRECT_MESSAGE', text: 'second human message' },
419
+ ])
420
+ expect(log).toMatchSnapshot()
421
+ })
422
+
423
+ it('context compaction outside a stream emits append+isCompacting metadata; inside a stream it is cumulative', () => {
424
+ const { log, feed } = setup()
425
+ feed([
426
+ // standalone (no open stream)
427
+ { type: 'CONTEXT_COMPACTION_START' },
428
+ { type: 'CONTEXT_COMPACTION_END', text: 'Summarized 12 messages' },
429
+ ])
430
+ const standaloneLog = [...log]
431
+ log.length = 0
432
+ feed([
433
+ { type: 'MESSAGE_START' },
434
+ { type: 'CONTEXT_COMPACTION_START' },
435
+ { type: 'CONTEXT_COMPACTION_END', text: 'Mid-stream summary' },
436
+ { type: 'MESSAGE_END' },
437
+ ])
438
+ expect({ standalone: standaloneLog, inStream: log }).toMatchSnapshot()
439
+ })
440
+
441
+ it('reset() clears accumulator + stream flags so the next dialog cold-starts cumulative', () => {
442
+ const { log, feed, reducer } = setup()
443
+ feed([
444
+ { type: 'MESSAGE_START' },
445
+ { type: 'TEXT', text: 'dialog one' },
446
+ { type: 'MESSAGE_END' },
447
+ ])
448
+ reducer.reset()
449
+ log.length = 0
450
+ feed([{ type: 'TEXT', text: 'dialog two cold start' }])
451
+ expect(log).toMatchSnapshot()
452
+ })
453
+
454
+ it('initialState resume: continuation chunks after resume take the post-stream append path', () => {
455
+ const { log } = setup({
456
+ initialState: {
457
+ existingSegments: [{ type: 'text', text: 'restored partial ' }],
458
+ escalatedApprovals: new Map([
459
+ ['req-esc', { command: 'escalated cmd', approvalType: 'ADMIN' }],
460
+ ]),
461
+ },
462
+ })
463
+ // initializeWithState replays escalated approvals via onEscalatedApproval
464
+ // and marks hasEverStreamed=true.
465
+ expect(log).toMatchSnapshot()
466
+ })
467
+ })