@flamingo-stack/openframe-frontend-core 0.0.458-snapshot.20260720215024 → 0.0.458

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 (281) hide show
  1. package/dist/{chunk-BLZZXZNM.cjs → chunk-5USSSRAL.cjs} +26 -26
  2. package/dist/{chunk-BLZZXZNM.cjs.map → chunk-5USSSRAL.cjs.map} +1 -1
  3. package/dist/{chunk-CGNDAJ7V.js → chunk-6B27O3ZB.js} +4 -4
  4. package/dist/{chunk-P5JQDFRM.cjs → chunk-7IRPMNRL.cjs} +60 -60
  5. package/dist/chunk-7IRPMNRL.cjs.map +1 -0
  6. package/dist/{chunk-4XDWNAZW.cjs → chunk-DQ3EHM6G.cjs} +9 -9
  7. package/dist/{chunk-4XDWNAZW.cjs.map → chunk-DQ3EHM6G.cjs.map} +1 -1
  8. package/dist/{chunk-7KSEINAE.cjs → chunk-FTXDIDNX.cjs} +15 -15
  9. package/dist/{chunk-7KSEINAE.cjs.map → chunk-FTXDIDNX.cjs.map} +1 -1
  10. package/dist/{chunk-4R6H2U77.js → chunk-H7ETLG65.js} +4 -4
  11. package/dist/{chunk-LAOO7XHO.js → chunk-HWTUVLYB.js} +2 -2
  12. package/dist/{chunk-F2NMWV44.js → chunk-IDKDOQZL.js} +2 -2
  13. package/dist/{chunk-BQ7PMWLM.cjs → chunk-KIIOBK7G.cjs} +27 -28
  14. package/dist/chunk-KIIOBK7G.cjs.map +1 -0
  15. package/dist/{chunk-QO2XD3FR.js → chunk-KQGFKG6Y.js} +2 -2
  16. package/dist/{chunk-3N3TMZ62.cjs → chunk-L676XVP4.cjs} +7 -7
  17. package/dist/{chunk-3N3TMZ62.cjs.map → chunk-L676XVP4.cjs.map} +1 -1
  18. package/dist/{chunk-F7F43U7Q.cjs → chunk-LDAOPWXZ.cjs} +11 -11
  19. package/dist/{chunk-F7F43U7Q.cjs.map → chunk-LDAOPWXZ.cjs.map} +1 -1
  20. package/dist/{chunk-ADD3FPDG.cjs → chunk-MKLP2SOZ.cjs} +4886 -7004
  21. package/dist/chunk-MKLP2SOZ.cjs.map +1 -0
  22. package/dist/{chunk-VXJH5TDN.js → chunk-QL7ODLJA.js} +10 -10
  23. package/dist/chunk-QL7ODLJA.js.map +1 -0
  24. package/dist/{chunk-OR5AMXYN.js → chunk-R5QYMUKN.js} +2 -2
  25. package/dist/{chunk-REWRUV3K.js → chunk-TNLFAJPA.js} +9673 -11791
  26. package/dist/chunk-TNLFAJPA.js.map +1 -0
  27. package/dist/{chunk-XF5ROTMQ.js → chunk-U2YDR5DT.js} +2 -2
  28. package/dist/{chunk-PXZ7YQ5V.cjs → chunk-VTQSB6QB.cjs} +5 -5
  29. package/dist/{chunk-PXZ7YQ5V.cjs.map → chunk-VTQSB6QB.cjs.map} +1 -1
  30. package/dist/{chunk-UI7CIUAR.js → chunk-WGJPTFRH.js} +2 -2
  31. package/dist/{chunk-WCE66C2Z.cjs → chunk-XUNJILJT.cjs} +62 -62
  32. package/dist/{chunk-WCE66C2Z.cjs.map → chunk-XUNJILJT.cjs.map} +1 -1
  33. package/dist/{chunk-APF5QBAU.js → chunk-YQBPIUZU.js} +2 -2
  34. package/dist/{chunk-TA7MFVUS.cjs → chunk-YV2YA3QH.cjs} +31 -31
  35. package/dist/{chunk-TA7MFVUS.cjs.map → chunk-YV2YA3QH.cjs.map} +1 -1
  36. package/dist/{chunk-QSGZE6AZ.cjs → chunk-ZDJ4ZUQ4.cjs} +37 -37
  37. package/dist/{chunk-QSGZE6AZ.cjs.map → chunk-ZDJ4ZUQ4.cjs.map} +1 -1
  38. package/dist/{chunk-LJKZIIK4.js → chunk-ZHQQRYMB.js} +5 -6
  39. package/dist/chunk-ZHQQRYMB.js.map +1 -0
  40. package/dist/components/case-studies/index.cjs +8 -8
  41. package/dist/components/case-studies/index.js +2 -2
  42. package/dist/components/chart.d.ts +1 -1
  43. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  44. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  45. package/dist/components/chat/hooks/index.d.ts +1 -0
  46. package/dist/components/chat/hooks/index.d.ts.map +1 -1
  47. package/dist/components/chat/hooks/use-chat.d.ts.map +1 -1
  48. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +48 -15
  49. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
  50. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts +6 -0
  51. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +1 -0
  52. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +47 -3
  53. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
  54. package/dist/components/chat/index.cjs +2 -10
  55. package/dist/components/chat/index.cjs.map +1 -1
  56. package/dist/components/chat/index.d.ts +0 -1
  57. package/dist/components/chat/index.d.ts.map +1 -1
  58. package/dist/components/chat/index.js +13 -21
  59. package/dist/components/chat/types/api.types.d.ts +81 -1
  60. package/dist/components/chat/types/api.types.d.ts.map +1 -1
  61. package/dist/components/chat/types/processing.types.d.ts +90 -2
  62. package/dist/components/chat/types/processing.types.d.ts.map +1 -1
  63. package/dist/components/chat/utils/chunk-parser.d.ts +25 -0
  64. package/dist/components/chat/utils/chunk-parser.d.ts.map +1 -0
  65. package/dist/components/chat/utils/extract-incomplete-message-state.d.ts +6 -34
  66. package/dist/components/chat/utils/extract-incomplete-message-state.d.ts.map +1 -1
  67. package/dist/components/chat/utils/index.d.ts +3 -2
  68. package/dist/components/chat/utils/index.d.ts.map +1 -1
  69. package/dist/components/chat/utils/process-historical-messages.d.ts +11 -59
  70. package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
  71. package/dist/components/contact/index.cjs +3 -3
  72. package/dist/components/contact/index.js +2 -2
  73. package/dist/components/docs/index.cjs +5 -5
  74. package/dist/components/docs/index.js +4 -4
  75. package/dist/components/embeds/index.cjs +3 -3
  76. package/dist/components/embeds/index.js +2 -2
  77. package/dist/components/faq/index.cjs +3 -3
  78. package/dist/components/faq/index.js +2 -2
  79. package/dist/components/features/index.cjs +2 -2
  80. package/dist/components/features/index.js +1 -1
  81. package/dist/components/help-center-pages/index.cjs +20 -20
  82. package/dist/components/help-center-pages/index.js +11 -11
  83. package/dist/components/index.cjs +129 -171
  84. package/dist/components/index.cjs.map +1 -1
  85. package/dist/components/index.js +21 -63
  86. package/dist/components/index.js.map +1 -1
  87. package/dist/components/navigation/index.cjs +2 -2
  88. package/dist/components/navigation/index.js +1 -1
  89. package/dist/components/onboarding-guides/index.cjs +5 -5
  90. package/dist/components/onboarding-guides/index.js +4 -4
  91. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
  92. package/dist/components/related-content/index.cjs +3 -3
  93. package/dist/components/related-content/index.js +2 -2
  94. package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
  95. package/dist/components/tickets/index.cjs +5 -5
  96. package/dist/components/tickets/index.js +4 -4
  97. package/dist/components/ui/index.cjs +2 -44
  98. package/dist/components/ui/index.cjs.map +1 -1
  99. package/dist/components/ui/index.d.ts +2 -1
  100. package/dist/components/ui/index.d.ts.map +1 -1
  101. package/dist/components/ui/index.js +13 -55
  102. package/dist/components/ui/rich-markdown-renderer.d.ts +34 -0
  103. package/dist/components/ui/rich-markdown-renderer.d.ts.map +1 -0
  104. package/dist/components/ui/simple-markdown-renderer.d.ts +73 -0
  105. package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -0
  106. package/dist/index.cjs +2 -60
  107. package/dist/index.cjs.map +1 -1
  108. package/dist/index.js +13 -71
  109. package/dist/utils/index.cjs +40 -169
  110. package/dist/utils/index.cjs.map +1 -1
  111. package/dist/utils/index.d.ts +0 -1
  112. package/dist/utils/index.d.ts.map +1 -1
  113. package/dist/utils/index.js +41 -162
  114. package/dist/utils/index.js.map +1 -1
  115. package/dist/utils/markdown-section-extractor.d.ts.map +1 -1
  116. package/package.json +1 -7
  117. package/src/components/chat/__tests__/chat-message-list.test.tsx +5 -293
  118. package/src/components/chat/chat-message-enhanced.tsx +17 -111
  119. package/src/components/chat/chat-message-list.tsx +113 -367
  120. package/src/components/chat/embeddable-chat.tsx +0 -6
  121. package/src/components/chat/hooks/.index.md +1 -1
  122. package/src/components/chat/hooks/.use-nats-chat-adapter.md +1 -1
  123. package/src/components/chat/hooks/.use-realtime-chunk-processor.md +50 -0
  124. package/src/components/chat/hooks/index.ts +1 -0
  125. package/src/components/chat/hooks/use-chat.ts +0 -8
  126. package/src/components/chat/hooks/use-nats-chat-adapter.ts +822 -243
  127. package/src/components/chat/hooks/use-realtime-chunk-processor.ts +479 -0
  128. package/src/components/chat/hooks/use-sse-chat-adapter.ts +666 -318
  129. package/src/components/chat/index.ts +0 -5
  130. package/src/components/chat/thinking-display.tsx +1 -1
  131. package/src/components/chat/types/.api.types.md +3 -1
  132. package/src/components/chat/types/.processing.types.md +23 -6
  133. package/src/components/chat/types/api.types.ts +73 -6
  134. package/src/components/chat/types/processing.types.ts +52 -11
  135. package/src/components/chat/utils/.chunk-parser.md +51 -0
  136. package/src/components/chat/utils/.index.md +5 -0
  137. package/src/components/chat/utils/chunk-parser.ts +255 -0
  138. package/src/components/chat/utils/extract-incomplete-message-state.ts +5 -63
  139. package/src/components/chat/utils/index.ts +8 -5
  140. package/src/components/chat/utils/process-historical-messages.ts +383 -352
  141. package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +4 -22
  142. package/src/components/shared/legal-document/legal-document-page.tsx +1 -1
  143. package/src/components/shared/product-release/release-detail-page.tsx +4 -19
  144. package/src/components/ui/.simple-markdown-renderer.md +40 -0
  145. package/src/components/ui/index.ts +2 -1
  146. package/src/components/ui/release-changelog-section.tsx +1 -1
  147. package/src/components/ui/rich-markdown-renderer.tsx +1223 -0
  148. package/src/components/ui/simple-markdown-renderer.tsx +965 -0
  149. package/src/components/ui/ticket-info-section.tsx +1 -1
  150. package/src/utils/index.ts +0 -1
  151. package/src/utils/markdown-section-extractor.ts +56 -41
  152. package/dist/chat-protocol/decode.d.ts +0 -58
  153. package/dist/chat-protocol/decode.d.ts.map +0 -1
  154. package/dist/chat-protocol/encode.d.ts +0 -44
  155. package/dist/chat-protocol/encode.d.ts.map +0 -1
  156. package/dist/chat-protocol/env-flag.d.ts +0 -35
  157. package/dist/chat-protocol/env-flag.d.ts.map +0 -1
  158. package/dist/chat-protocol/events.d.ts +0 -192
  159. package/dist/chat-protocol/events.d.ts.map +0 -1
  160. package/dist/chat-protocol/frames.d.ts +0 -206
  161. package/dist/chat-protocol/frames.d.ts.map +0 -1
  162. package/dist/chat-protocol/index.cjs +0 -493
  163. package/dist/chat-protocol/index.cjs.map +0 -1
  164. package/dist/chat-protocol/index.d.ts +0 -18
  165. package/dist/chat-protocol/index.d.ts.map +0 -1
  166. package/dist/chat-protocol/index.js +0 -477
  167. package/dist/chat-protocol/index.js.map +0 -1
  168. package/dist/chat-protocol/ip-normalize.d.ts +0 -44
  169. package/dist/chat-protocol/ip-normalize.d.ts.map +0 -1
  170. package/dist/chat-protocol/nats-decoder.d.ts +0 -26
  171. package/dist/chat-protocol/nats-decoder.d.ts.map +0 -1
  172. package/dist/chunk-ADD3FPDG.cjs.map +0 -1
  173. package/dist/chunk-BQ7PMWLM.cjs.map +0 -1
  174. package/dist/chunk-LJKZIIK4.js.map +0 -1
  175. package/dist/chunk-P5JQDFRM.cjs.map +0 -1
  176. package/dist/chunk-REWRUV3K.js.map +0 -1
  177. package/dist/chunk-VXJH5TDN.js.map +0 -1
  178. package/dist/components/chat/stream/chat-dialog-store.d.ts +0 -184
  179. package/dist/components/chat/stream/chat-dialog-store.d.ts.map +0 -1
  180. package/dist/components/chat/stream/chat-stream-reducer.d.ts +0 -367
  181. package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +0 -1
  182. package/dist/components/chat/stream/delta-batcher.d.ts +0 -51
  183. package/dist/components/chat/stream/delta-batcher.d.ts.map +0 -1
  184. package/dist/components/chat/stream/index.d.ts +0 -17
  185. package/dist/components/chat/stream/index.d.ts.map +0 -1
  186. package/dist/components/chat/stream/message-mutations.d.ts +0 -77
  187. package/dist/components/chat/stream/message-mutations.d.ts.map +0 -1
  188. package/dist/components/chat/stream/use-chat-stream-reducer.d.ts +0 -22
  189. package/dist/components/chat/stream/use-chat-stream-reducer.d.ts.map +0 -1
  190. package/dist/components/ui/markdown/base-components.d.ts +0 -56
  191. package/dist/components/ui/markdown/base-components.d.ts.map +0 -1
  192. package/dist/components/ui/markdown/engine.d.ts +0 -99
  193. package/dist/components/ui/markdown/engine.d.ts.map +0 -1
  194. package/dist/components/ui/markdown/heading-ids.d.ts +0 -65
  195. package/dist/components/ui/markdown/heading-ids.d.ts.map +0 -1
  196. package/dist/components/ui/markdown/index.d.ts +0 -18
  197. package/dist/components/ui/markdown/index.d.ts.map +0 -1
  198. package/dist/components/ui/markdown/mermaid-diagram.d.ts +0 -79
  199. package/dist/components/ui/markdown/mermaid-diagram.d.ts.map +0 -1
  200. package/dist/components/ui/markdown/rich/embed-overrides.d.ts +0 -14
  201. package/dist/components/ui/markdown/rich/embed-overrides.d.ts.map +0 -1
  202. package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts +0 -40
  203. package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts.map +0 -1
  204. package/dist/components/ui/markdown/rich/shortcodes.d.ts +0 -8
  205. package/dist/components/ui/markdown/rich/shortcodes.d.ts.map +0 -1
  206. package/dist/components/ui/markdown/sanitize.d.ts +0 -153
  207. package/dist/components/ui/markdown/sanitize.d.ts.map +0 -1
  208. package/dist/components/ui/markdown/simple-markdown-renderer.d.ts +0 -23
  209. package/dist/components/ui/markdown/simple-markdown-renderer.d.ts.map +0 -1
  210. package/dist/components/ui/markdown/streaming.d.ts +0 -78
  211. package/dist/components/ui/markdown/streaming.d.ts.map +0 -1
  212. package/dist/components/ui/markdown/text-size.d.ts +0 -34
  213. package/dist/components/ui/markdown/text-size.d.ts.map +0 -1
  214. package/dist/utils/markdown-fences.d.ts +0 -42
  215. package/dist/utils/markdown-fences.d.ts.map +0 -1
  216. package/dist/utils/markdown-heading-id.d.ts +0 -85
  217. package/dist/utils/markdown-heading-id.d.ts.map +0 -1
  218. package/src/chat-protocol/__tests__/__snapshots__/nats-decoder-golden.test.ts.snap +0 -307
  219. package/src/chat-protocol/__tests__/chat-protocol.test.ts +0 -515
  220. package/src/chat-protocol/__tests__/env-flag.test.ts +0 -52
  221. package/src/chat-protocol/__tests__/ip-normalize.test.ts +0 -136
  222. package/src/chat-protocol/__tests__/nats-decoder-golden.test.ts +0 -228
  223. package/src/chat-protocol/decode.ts +0 -277
  224. package/src/chat-protocol/encode.ts +0 -71
  225. package/src/chat-protocol/env-flag.ts +0 -39
  226. package/src/chat-protocol/events.ts +0 -228
  227. package/src/chat-protocol/frames.ts +0 -238
  228. package/src/chat-protocol/index.ts +0 -21
  229. package/src/chat-protocol/ip-normalize.ts +0 -146
  230. package/src/chat-protocol/nats-decoder.ts +0 -252
  231. package/src/components/chat/__tests__/chat-message-streaming-memo.test.tsx +0 -207
  232. package/src/components/chat/__tests__/chat-pending-turn.test.tsx +0 -209
  233. package/src/components/chat/hooks/__tests__/__snapshots__/persisted-state-v1-golden.test.ts.snap +0 -297
  234. package/src/components/chat/hooks/__tests__/__snapshots__/sse-stream-golden.test.ts.snap +0 -0
  235. package/src/components/chat/hooks/__tests__/persisted-state-v1-golden.test.ts +0 -272
  236. package/src/components/chat/hooks/__tests__/sse-stream-golden.test.ts +0 -318
  237. package/src/components/chat/stream/__tests__/__snapshots__/chat-stream-reducer-golden.test.ts.snap +0 -937
  238. package/src/components/chat/stream/__tests__/chat-dialog-store.test.ts +0 -756
  239. package/src/components/chat/stream/__tests__/chat-stream-reducer-golden.test.ts +0 -460
  240. package/src/components/chat/stream/__tests__/chat-stream-reducer.test.ts +0 -894
  241. package/src/components/chat/stream/__tests__/delta-batcher.test.ts +0 -255
  242. package/src/components/chat/stream/__tests__/use-chat-stream-reducer.test.ts +0 -98
  243. package/src/components/chat/stream/chat-dialog-store.ts +0 -536
  244. package/src/components/chat/stream/chat-stream-reducer.ts +0 -1796
  245. package/src/components/chat/stream/delta-batcher.ts +0 -159
  246. package/src/components/chat/stream/index.ts +0 -55
  247. package/src/components/chat/stream/message-mutations.ts +0 -338
  248. package/src/components/chat/stream/use-chat-stream-reducer.ts +0 -126
  249. package/src/components/chat/utils/__tests__/__snapshots__/process-historical-messages-golden.test.ts.snap +0 -418
  250. package/src/components/chat/utils/__tests__/__snapshots__/segment-accumulator-golden.test.ts.snap +0 -599
  251. package/src/components/chat/utils/__tests__/process-historical-messages-golden.test.ts +0 -317
  252. package/src/components/chat/utils/__tests__/segment-accumulator-golden.test.ts +0 -270
  253. package/src/components/ui/__tests__/__snapshots__/markdown-parity.test.tsx.snap +0 -2420
  254. package/src/components/ui/__tests__/markdown-parity.test.tsx +0 -2528
  255. package/src/components/ui/markdown/__tests__/mermaid-security.test.ts +0 -115
  256. package/src/components/ui/markdown/__tests__/mermaid-stale-render.test.tsx +0 -95
  257. package/src/components/ui/markdown/__tests__/sanitize-invariant.test.ts +0 -309
  258. package/src/components/ui/markdown/__tests__/streaming.test.tsx +0 -388
  259. package/src/components/ui/markdown/base-components.tsx +0 -341
  260. package/src/components/ui/markdown/engine.tsx +0 -315
  261. package/src/components/ui/markdown/heading-ids.ts +0 -239
  262. package/src/components/ui/markdown/index.ts +0 -49
  263. package/src/components/ui/markdown/mermaid-diagram.tsx +0 -291
  264. package/src/components/ui/markdown/rich/embed-overrides.tsx +0 -199
  265. package/src/components/ui/markdown/rich/rich-markdown-renderer.tsx +0 -184
  266. package/src/components/ui/markdown/rich/shortcodes.ts +0 -170
  267. package/src/components/ui/markdown/sanitize.ts +0 -3499
  268. package/src/components/ui/markdown/simple-markdown-renderer.tsx +0 -28
  269. package/src/components/ui/markdown/streaming.ts +0 -362
  270. package/src/components/ui/markdown/text-size.ts +0 -106
  271. package/src/utils/markdown-fences.ts +0 -127
  272. package/src/utils/markdown-heading-id.ts +0 -348
  273. /package/dist/{chunk-CGNDAJ7V.js.map → chunk-6B27O3ZB.js.map} +0 -0
  274. /package/dist/{chunk-4R6H2U77.js.map → chunk-H7ETLG65.js.map} +0 -0
  275. /package/dist/{chunk-LAOO7XHO.js.map → chunk-HWTUVLYB.js.map} +0 -0
  276. /package/dist/{chunk-F2NMWV44.js.map → chunk-IDKDOQZL.js.map} +0 -0
  277. /package/dist/{chunk-QO2XD3FR.js.map → chunk-KQGFKG6Y.js.map} +0 -0
  278. /package/dist/{chunk-OR5AMXYN.js.map → chunk-R5QYMUKN.js.map} +0 -0
  279. /package/dist/{chunk-XF5ROTMQ.js.map → chunk-U2YDR5DT.js.map} +0 -0
  280. /package/dist/{chunk-UI7CIUAR.js.map → chunk-WGJPTFRH.js.map} +0 -0
  281. /package/dist/{chunk-APF5QBAU.js.map → chunk-YQBPIUZU.js.map} +0 -0
@@ -1,71 +0,0 @@
1
- /**
2
- * SSE wire-protocol encoders — the emit side of the framing contract in
3
- * `./frames.ts`. Server-safe (TextEncoder only). The hub's stream route
4
- * consumes these so emitter and decoder can never drift.
5
- */
6
-
7
- import {
8
- FRAME_TERMINATOR,
9
- END_OF_LEADING,
10
- TRAILER_SENTINEL,
11
- type SseLeadingFrame,
12
- type SseTrailingUsageFrame,
13
- } from './frames'
14
-
15
- const encoder = new TextEncoder()
16
-
17
- /** Matches every framing sentinel byte: `\0`, `\x1E`, `\x1F`. THE one
18
- * regex — `stripSentinelBytes` is its only consumer. */
19
- const SENTINEL_BYTES_RE = /[\u0000\u001E\u001F]/g
20
-
21
- /**
22
- * Remove the SSE framing sentinel bytes (`\0`, `\x1E`, `\x1F`) from model
23
- * text. Exported as a STANDALONE helper — not just folded into
24
- * `encodeTextDelta` — because producers must strip at the point where they
25
- * first take custody of the text, BEFORE any local accumulation.
26
- *
27
- * Concretely: the hub's `claude-util.ts` accumulates `state.answerText` for
28
- * persistence + telemetry. If stripping only happened at encode time, the
29
- * persisted/telemetered answer would diverge, character for character, from
30
- * the bytes the user actually received whenever the model echoes a control
31
- * byte. Both sides call this, so there is exactly ONE definition of "which
32
- * bytes are framing" in the whole system — do not re-declare the regex.
33
- *
34
- * Idempotent and per-character, so it distributes over concatenation:
35
- * `strip(a + b) === strip(a) + strip(b)` — safe to apply per-delta or on the
36
- * accumulated string interchangeably.
37
- */
38
- export function stripSentinelBytes(text: string): string {
39
- return text.replace(SENTINEL_BYTES_RE, '')
40
- }
41
-
42
- /** Encode one leading frame: JSON + `\0` terminator. */
43
- export function encodeLeadingFrame(frame: SseLeadingFrame): Uint8Array {
44
- return encoder.encode(JSON.stringify(frame) + FRAME_TERMINATOR)
45
- }
46
-
47
- /** Encode the single `\x1E` end-of-leading-frames sentinel. */
48
- export function encodeEndOfLeading(): Uint8Array {
49
- return encoder.encode(END_OF_LEADING)
50
- }
51
-
52
- /**
53
- * Encode a raw answer-text delta. STRIPS the framing sentinel bytes via
54
- * `stripSentinelBytes` so model-echoed control bytes can no longer
55
- * mis-frame the stream (a literal `\x1F` in the answer used to flip the
56
- * client into trailer mode and swallow the rest of the answer PLUS the real
57
- * usage trailer — characterized by golden fixture (d)). Forward-looking
58
- * encoder fix only; the decoder's behavior is unchanged.
59
- *
60
- * Producers that ALSO accumulate the text locally (persistence, telemetry)
61
- * must call `stripSentinelBytes` on their own copy — see its docblock.
62
- */
63
- export function encodeTextDelta(text: string): Uint8Array {
64
- return encoder.encode(stripSentinelBytes(text))
65
- }
66
-
67
- /** Encode the trailing usage frame: `\x1F` + JSON, no terminator
68
- * (runs to stream end). */
69
- export function encodeTrailingUsageFrame(frame: SseTrailingUsageFrame): Uint8Array {
70
- return encoder.encode(TRAILER_SENTINEL + JSON.stringify(frame))
71
- }
@@ -1,39 +0,0 @@
1
- /**
2
- * `envFlagEnabled` — THE cross-repo predicate for reading a boolean env flag.
3
- *
4
- * WHY IT LIVES HERE: the same flag is read on BOTH sides of the guide-chat
5
- * seam and each side had grown its own reading of it. The hub parsed the
6
- * value (`'0'` / `'false'` / `'off'` mean OFF); the producing app used bare
7
- * `Boolean(process.env.X)`, under which every non-empty string — including
8
- * `'0'` and `'false'` — is TRUE.
9
- *
10
- * That divergence failed OPEN on the one flag that gates a security boundary.
11
- * `TRUSTED_INGRESS_SETS_REAL_IP` is an operator's assertion that a reverse
12
- * proxy OVERWRITES the client-IP headers; without it those headers are
13
- * attacker-writable and must not be read. An operator writing `=0` to mean
14
- * "off" got the hub honoring that while the producer read `x-real-ip` /
15
- * `x-forwarded-for` anyway and forwarded the value as `x-chat-ip`, which the
16
- * hub then trusts verbatim under the service token. A rate-limit-bucket
17
- * spoof, reachable through a plausible operator typo.
18
- *
19
- * Both repos already depend on this package and `./chat-protocol` is its
20
- * server-safe subpath (no React, no browser APIs), so this is the one place
21
- * both sides can share — same reasoning that moved `normalizeIpForBucketKey`
22
- * here. Keep it as ONE definition: a second copy is what caused the drift.
23
- *
24
- * Contract:
25
- * - unset, empty, or whitespace-only → `false`;
26
- * - `'0'`, `'false'`, `'off'` → `false` (case- and
27
- * surrounding-whitespace-insensitive);
28
- * - any other non-empty value → `true`.
29
- *
30
- * `process.env` is read PER CALL, never module-hoisted, so tests, preview and
31
- * prod all observe the live value rather than whatever was present at
32
- * module-eval time.
33
- */
34
- export function envFlagEnabled(name: string): boolean {
35
- const raw = process.env[name]
36
- if (!raw) return false
37
- const v = raw.trim().toLowerCase()
38
- return v !== '' && v !== '0' && v !== 'false' && v !== 'off'
39
- }
@@ -1,228 +0,0 @@
1
- /**
2
- * Normalized chat stream events — the transport-agnostic event union BOTH
3
- * decoders (SSE byte framing in `./decode.ts`, NATS chunks in
4
- * `./nats-decoder.ts`) emit. Phase 3 of the chat unification makes the
5
- * reducer consume these directly; today the SSE adapter maps them back to
6
- * legacy `MessageSegment` yields.
7
- *
8
- * Server-safe: no React, no browser APIs.
9
- */
10
-
11
- // The wire-frame shapes these events carry through are defined ONCE in
12
- // `./frames.ts` — reuse them here rather than restating their fields.
13
- import type {
14
- ApprovalRequestField,
15
- DecisionResolvedFrame,
16
- UsageTelemetry,
17
- } from './frames'
18
-
19
- /** Optional envelope on every event. `seq` carries the transport's
20
- * stream sequence (JetStream `streamSeq` on NATS; unused on SSE). */
21
- interface ChatStreamEventBase {
22
- seq?: number
23
- }
24
-
25
- /** Stream entered answer-text mode (SSE: the `\x1E` sentinel or the
26
- * JSON-parse-failure fallback; NATS: MESSAGE_START).
27
- * `implicit` is true ONLY for the SSE fallback path where a
28
- * non-JSON leading buffer flips straight into text mode — consumers
29
- * that flush coalesced thinking on turn-start must SKIP the flush for
30
- * implicit starts (legacy adapter parity: the fallback path never
31
- * flushed pending thinking before the text). */
32
- export interface TurnStartEvent extends ChatStreamEventBase {
33
- type: 'turn-start'
34
- implicit?: boolean
35
- }
36
-
37
- export interface TurnEndEvent extends ChatStreamEventBase {
38
- type: 'turn-end'
39
- }
40
-
41
- /** Answer text delta. `leading: true` marks SSE `text-leading` frames
42
- * (model preamble prose emitted BEFORE the tool approval card). */
43
- export interface TextDeltaEvent extends ChatStreamEventBase {
44
- type: 'text-delta'
45
- text: string
46
- leading?: boolean
47
- }
48
-
49
- /** Thinking delta — APPEND-ONLY contract: each event carries the next
50
- * verbatim slice; consumers accumulate. Decoders never diff. */
51
- export interface ThinkingDeltaEvent extends ChatStreamEventBase {
52
- type: 'thinking-delta'
53
- text: string
54
- }
55
-
56
- export interface StatusEvent extends ChatStreamEventBase {
57
- type: 'status'
58
- phase: 'thinking'
59
- }
60
-
61
- /** NATS tool execution progress (EXECUTING_TOOL / EXECUTED_TOOL). */
62
- export interface ToolExecutionEvent extends ChatStreamEventBase {
63
- type: 'tool-execution'
64
- data: {
65
- type: 'EXECUTING_TOOL' | 'EXECUTED_TOOL'
66
- integratedToolType: string
67
- toolFunction: string
68
- toolTitle?: string
69
- parameters?: Record<string, unknown>
70
- result?: string
71
- success?: boolean
72
- toolExecutionRequestId?: string
73
- }
74
- }
75
-
76
- /** Single tool call inside a batch approval request (NATS). */
77
- export interface ApprovalToolCall {
78
- toolExecutionRequestId: string
79
- toolName: string
80
- toolTitle?: string
81
- toolExplanation?: string
82
- toolType?: string
83
- requiresApproval: boolean
84
- approvalType?: string | null
85
- toolCallArguments?: Record<string, unknown> | null
86
- }
87
-
88
- /** A tool call awaits user approval. SSE fills `command`/`fields`
89
- * (card-ready payload); NATS fills `command`/`explanation` or
90
- * `toolCalls` (batch form). */
91
- export interface ApprovalRequestEvent extends ChatStreamEventBase {
92
- type: 'approval-request'
93
- requestId: string
94
- /** SSE: the write tool's name. NATS: approval tier (USER/ADMIN/…). */
95
- approvalType?: string
96
- command?: string
97
- explanation?: string
98
- fields?: ApprovalRequestField[]
99
- toolCalls?: ApprovalToolCall[]
100
- status?: 'pending'
101
- }
102
-
103
- /** An approval request was resolved (SSE `decision_resolved` frame /
104
- * NATS APPROVAL_RESULT chunk). */
105
- export interface ApprovalResolvedEvent extends ChatStreamEventBase {
106
- type: 'approval-resolved'
107
- requestId?: string
108
- status: 'approved' | 'rejected'
109
- ok?: boolean
110
- toolName?: string
111
- approvalType?: string
112
- resolvedByName?: string | null
113
- receiptText?: string
114
- /** Inline post-approve card: the ref payload + its documentType +
115
- * the `[card://…]` marker (SSE only). */
116
- cardRef?: unknown
117
- cardType?: string
118
- marker?: string
119
- result?: DecisionResolvedFrame['result']
120
- willAutoContinue?: boolean
121
- }
122
-
123
- /** Per-turn metadata. Raw wire values pass through UNVALIDATED — the
124
- * consumer replicates the legacy truthiness/typeof gates (so a
125
- * malformed frame degrades identically to the pre-SSOT parser). */
126
- export interface ChatMetadataEvent extends ChatStreamEventBase {
127
- type: 'metadata'
128
- provider?: string | null
129
- modelLabel?: string | null
130
- /** Raw model id (SSE `meta.model`; NATS `modelName`). */
131
- modelName?: string | null
132
- contextWindowMaxTokens?: number | null
133
- sources?: unknown
134
- refs?: unknown
135
- scrollAnchor?: unknown
136
- routing?: {
137
- routedComplexity: string
138
- routedModel?: string
139
- routedThinkingBudget: number | null
140
- }
141
- }
142
-
143
- /** SSE usage frames — raw wire keys (snake_case) preserved. */
144
- export interface UsageEvent extends ChatStreamEventBase {
145
- type: 'usage'
146
- stage: 'start' | 'end'
147
- input_tokens?: number
148
- output_tokens?: number
149
- cache_read_input_tokens?: number
150
- cache_creation_input_tokens?: number
151
- hit_rate_pct?: number
152
- telemetry?: UsageTelemetry
153
- /** Left OPAQUE on purpose: the consumer (`chat-stream-reducer`'s
154
- * `applySseUsage`) re-validates every nested field with the legacy
155
- * truthiness/typeof gates, so a malformed frame degrades identically
156
- * to the pre-SSOT parser. Typing it would imply guarantees the wire
157
- * does not make. */
158
- breakdown?: unknown
159
- debug?: unknown
160
- }
161
-
162
- /** NATS TOKEN_USAGE chunk (camelCase backend shape). */
163
- export interface TokenUsageEvent extends ChatStreamEventBase {
164
- type: 'token-usage'
165
- inputTokensSize: number
166
- outputTokensSize: number
167
- totalTokensSize: number
168
- contextSize: number
169
- }
170
-
171
- export interface CompactionEvent extends ChatStreamEventBase {
172
- type: 'compaction'
173
- phase: 'start' | 'end'
174
- summary?: string
175
- }
176
-
177
- export interface ErrorEvent extends ChatStreamEventBase {
178
- type: 'error'
179
- title: string
180
- details?: string
181
- }
182
-
183
- /** Non-assistant message on the stream (NATS): the user's own message
184
- * echo (`message-request`), an operator direct message, or a system
185
- * line. */
186
- /**
187
- * Dialog participant owner type. The two members below are the ones clients
188
- * BRANCH ON (admin-vs-not decides echo dedup and author styling); the union
189
- * stays open (`string & {}`) because the wire may carry other roles that the
190
- * client treats as "not admin". Always compare against `CHAT_OWNER_ADMIN`,
191
- * never a bare `'ADMIN'` literal — a typo in a literal silently disables
192
- * dedup instead of failing to compile.
193
- */
194
- export type ChatOwnerType = 'ADMIN' | 'CLIENT' | (string & {})
195
-
196
- /** Canonical ADMIN owner-type token (see `ChatOwnerType`). */
197
- export const CHAT_OWNER_ADMIN = 'ADMIN'
198
-
199
- export interface ParticipantEvent extends ChatStreamEventBase {
200
- type: 'participant'
201
- kind: 'message-request' | 'direct-message' | 'system'
202
- text: string
203
- ownerType?: ChatOwnerType
204
- displayName?: string
205
- userId?: string
206
- contextItems?: Array<{ type: string; id: string; label: string }>
207
- }
208
-
209
- export interface DialogClosedEvent extends ChatStreamEventBase {
210
- type: 'dialog-closed'
211
- }
212
-
213
- export type ChatStreamEvent =
214
- | TurnStartEvent
215
- | TurnEndEvent
216
- | TextDeltaEvent
217
- | ThinkingDeltaEvent
218
- | StatusEvent
219
- | ToolExecutionEvent
220
- | ApprovalRequestEvent
221
- | ApprovalResolvedEvent
222
- | ChatMetadataEvent
223
- | UsageEvent
224
- | TokenUsageEvent
225
- | CompactionEvent
226
- | ErrorEvent
227
- | ParticipantEvent
228
- | DialogClosedEvent
@@ -1,238 +0,0 @@
1
- /**
2
- * SSE wire-protocol frame shapes — the byte-level contract between the
3
- * hub's chat stream emitter (`multi-platform-hub/lib/utils/claude-util.ts`)
4
- * and the lib's SSE decoder (`./decode.ts`).
5
- *
6
- * Wire format (custom byte framing, NOT standard SSE `data:` lines):
7
- *
8
- * [JSON frame]\0 [JSON frame]\0 … \x1E <raw UTF-8 answer deltas> \x1F [JSON usage trailer]
9
- *
10
- * 1. LEADING frames — each a JSON object terminated by `\0`
11
- * (FRAME_TERMINATOR). Status, metadata, routing, live thinking
12
- * deltas, usage:start, tool approval frames.
13
- * 2. ONE `\x1E` byte (END_OF_LEADING) — flips the stream into raw
14
- * UTF-8 answer-text mode.
15
- * 3. `\x1F` (TRAILER_SENTINEL) + one JSON usage frame running to
16
- * stream end (no terminator).
17
- *
18
- * Server-safe: no React, no browser APIs beyond TextEncoder/TextDecoder.
19
- */
20
-
21
- // =============================================================================
22
- // Sentinel constants
23
- // =============================================================================
24
-
25
- /** Terminates every leading JSON frame. */
26
- export const FRAME_TERMINATOR = '\0'
27
- /** Record Separator — end of leading frames, start of raw answer text. */
28
- export const END_OF_LEADING = '\x1E'
29
- /** Unit Separator — start of the trailing usage JSON frame. */
30
- export const TRAILER_SENTINEL = '\x1F'
31
-
32
- // =============================================================================
33
- // Routing types (moved verbatim from the hub's `lib/chat/wire-frames.ts`;
34
- // `RouteComplexity` is lib-local so the lib never imports hub code)
35
- // =============================================================================
36
-
37
- /** Server-side routing complexity tiers. Mirror of the hub's
38
- * `lib/constants/ai-models.ts` union — kept as a lib-local literal type
39
- * so the wire SSOT has zero hub imports. The DECODER accepts any string
40
- * (older/newer servers may ship values outside this union). */
41
- export type RouteComplexity = 'trivial' | 'default' | 'complex' | 'deep'
42
-
43
- /**
44
- * Routing decision frame. Emitted once per turn as a LEADING frame
45
- * (between metadata and the `\x1E` end-of-leading-frames sentinel) when
46
- * the server's `decideRoute()` produces a `Route`.
47
- *
48
- * Field names use the `routed*` prefix on PURPOSE — the client's
49
- * catch-all leading-frame branch inspects `meta.model` / `meta.modelLabel`.
50
- * A bare `model` field on this frame would OVERWRITE the metadata frame's
51
- * modelLabel and break the <ModelDisplay> badge. The `routed` prefix
52
- * sidesteps that collision.
53
- *
54
- * Older clients that don't recognize `kind: 'routing'` silently drop
55
- * the frame (the catch-all only matches frames carrying known fields
56
- * like `sources` / `refs` / `modelLabel`).
57
- */
58
- export interface RoutingFrame {
59
- kind: 'routing'
60
- routedComplexity: RouteComplexity
61
- routedModel: string
62
- routedThinkingBudget: number
63
- }
64
-
65
- /**
66
- * Optional field on the trailing usage frame's `breakdown`. Surfaces
67
- * per-route attribution to the admin test console so an operator can
68
- * see "this turn ran on Haiku/trivial/$0.0005" without re-parsing the
69
- * stream. Additive: clients that ignore unknown keys keep working.
70
- */
71
- export interface RoutedAnswerBreakdown {
72
- model: string
73
- complexity: RouteComplexity
74
- thinkingBudget: number
75
- }
76
-
77
- // =============================================================================
78
- // Leading frames
79
- // =============================================================================
80
-
81
- /** First frame on every stream — lets the shell render "Thinking…"
82
- * within ~200ms, before any upstream byte arrives. */
83
- export interface StatusThinkingFrame {
84
- status: 'thinking'
85
- }
86
-
87
- /** Per-turn metadata frame. The emitter sends `options.metadata`
88
- * verbatim; a separate refs-only frame may follow with the same shape.
89
- * All fields optional — the decoder's catch-all treats ANY frame that
90
- * didn't match a `kind` discriminant as metadata-ish. */
91
- export interface ChatMetadataFrame {
92
- /** Retrieval sources for the source-chip strip. Host-defined row
93
- * shape (`ChatSource` on the adapter side) — opaque at wire level. */
94
- sources?: unknown[]
95
- /** Per-row refs for inline object cards, keyed `<type>:<id>`. */
96
- refs?: Record<string, unknown>
97
- /** Raw model id (e.g. 'claude-sonnet-x'). Presence alone triggers the
98
- * client's meta merge; the value itself is not stored. */
99
- model?: string
100
- modelLabel?: string
101
- provider?: string
102
- contextWindowMaxTokens?: number
103
- /** Per-message viewport-positioning hint ('top' | 'bottom'). */
104
- scrollAnchor?: string
105
- }
106
-
107
- /** Live adaptive-thinking delta. WIRE IS ALREADY DELTA (Anthropic
108
- * thinking_delta slices) — decoders must NOT diff or re-accumulate. */
109
- export interface ThinkingDeltaFrame {
110
- kind: 'thinking-delta'
111
- text: string
112
- }
113
-
114
- /** Usage frame emitted as a LEADING frame right after Anthropic's
115
- * message_start (stage='start'). */
116
- export interface UsageStartFrame {
117
- kind: 'usage'
118
- stage: 'start'
119
- input_tokens: number
120
- cache_read_input_tokens?: number
121
- cache_creation_input_tokens?: number
122
- }
123
-
124
- /** Model preamble prose written BEFORE a tool_use block — emitted as a
125
- * standalone leading frame so it isn't stranded behind the approval
126
- * card (the `\x1E` sentinel is suppressed on tool turns). */
127
- export interface TextLeadingFrame {
128
- kind: 'text-leading'
129
- text: string
130
- }
131
-
132
- /** Tool invocation failed server-side (proposal persist error,
133
- * validation, ownership denial …). */
134
- export interface ToolErrorFrame {
135
- kind: 'tool_error'
136
- toolName?: string
137
- toolUseId?: string
138
- message: string
139
- }
140
-
141
- export interface ApprovalRequestField {
142
- label: string
143
- value: string
144
- }
145
-
146
- /** The model called a write tool; the server persisted a proposal and
147
- * ships a card-ready payload. Shape mirrors the hub's `onToolUse`
148
- * return in `lib/data/doc-chat-utils.ts`. */
149
- export interface ApprovalRequestFrame {
150
- kind: 'approval_request'
151
- proposalId: string
152
- toolName: string
153
- title?: string
154
- fields?: ApprovalRequestField[]
155
- preamble?: string | null
156
- args?: Record<string, unknown>
157
- expiresAt?: string
158
- ttlSeconds?: number
159
- }
160
-
161
- /** Server-driven post-approve / post-reject frame (confirm-tool route).
162
- * Mirror of the hub's `DecisionResolvedFrame` in
163
- * `lib/data/chat-agent-utils.ts` (tool_name widened to string — the
164
- * known-write-tool whitelist is host-side knowledge). */
165
- export interface DecisionResolvedFrame {
166
- kind: 'decision_resolved'
167
- /** The proposal this decision resolved — locates the SOURCE approval
168
- * card so the shell can flip its status + append the receipt. */
169
- proposalId: string
170
- ok: boolean
171
- action: 'approved' | 'rejected'
172
- tool_name?: string
173
- result?: {
174
- ticket_id?: string
175
- status?: string | null
176
- mirror_synced?: boolean
177
- }
178
- card?: {
179
- type: string
180
- marker: string
181
- ref: unknown
182
- }
183
- /** True when the server WILL pipe an auto-continuation turn after
184
- * this frame. */
185
- willAutoContinue: boolean
186
- /** Pre-rendered receipt copy from the source strategy's
187
- * `receiptRenderer` — client renders verbatim. */
188
- receiptText?: string
189
- }
190
-
191
- /** Every leading frame the emitter can produce. */
192
- export type SseLeadingFrame =
193
- | StatusThinkingFrame
194
- | ChatMetadataFrame
195
- | RoutingFrame
196
- | ThinkingDeltaFrame
197
- | UsageStartFrame
198
- | TextLeadingFrame
199
- | ToolErrorFrame
200
- | ApprovalRequestFrame
201
- | DecisionResolvedFrame
202
-
203
- // =============================================================================
204
- // Trailing usage frame
205
- // =============================================================================
206
-
207
- /** Card/chip emission counts for admin adoption tooling. */
208
- export interface UsageTelemetry {
209
- cards: number
210
- chips: number
211
- sentences: number
212
- answerLen: number
213
- }
214
-
215
- /** Trailing usage frame — `\x1F` + JSON, runs to stream end (no
216
- * terminator). `stage: 'display'` is a legacy alias the decoder treats
217
- * identically to `'end'`. */
218
- export interface SseTrailingUsageFrame {
219
- kind: 'usage'
220
- stage: 'end' | 'display'
221
- input_tokens?: number
222
- output_tokens?: number
223
- cache_read_input_tokens?: number
224
- cache_creation_input_tokens?: number
225
- hit_rate_pct?: number
226
- telemetry?: UsageTelemetry
227
- /** Cross-call usage breakdown (Haiku rewriter / classifier /
228
- * summarizer + routed-answer attribution). */
229
- breakdown?: {
230
- haikuRewriter?: { input: number; output: number }
231
- haikuClassifier?: { input: number; output: number }
232
- haikuSummarizer?: { input: number; output: number }
233
- routedAnswer?: RoutedAnswerBreakdown
234
- }
235
- /** Gated deep-debug payload (only present when the request carried
236
- * the privileged debug secret). */
237
- debug?: Record<string, unknown>
238
- }
@@ -1,21 +0,0 @@
1
- /**
2
- * Chat wire-protocol SSOT.
3
- *
4
- * The byte-level SSE framing contract (frames + encode + decode) and the
5
- * transport-agnostic `ChatStreamEvent` union both the SSE and NATS
6
- * decoders emit. Published as the server-safe `./chat-protocol` subpath —
7
- * no React, no browser APIs beyond TextEncoder/TextDecoder — so the hub's
8
- * stream route (emit side) and the lib's chat hooks (decode side) share
9
- * one protocol module.
10
- */
11
-
12
- export * from './frames'
13
- export * from './events'
14
- export * from './encode'
15
- export * from './decode'
16
- export * from './nats-decoder'
17
- // Cross-repo IP bucket-key normalizer (producer app + consumer hub share it).
18
- export * from './ip-normalize'
19
- // Cross-repo env-flag predicate — the trust assertion that gates the IP
20
- // forwarding above must be parsed IDENTICALLY on both sides of the seam.
21
- export * from './env-flag'