@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.
- package/dist/chat-protocol/decode.d.ts +58 -0
- package/dist/chat-protocol/decode.d.ts.map +1 -0
- package/dist/chat-protocol/encode.d.ts +44 -0
- package/dist/chat-protocol/encode.d.ts.map +1 -0
- package/dist/chat-protocol/env-flag.d.ts +35 -0
- package/dist/chat-protocol/env-flag.d.ts.map +1 -0
- package/dist/chat-protocol/events.d.ts +216 -0
- package/dist/chat-protocol/events.d.ts.map +1 -0
- package/dist/chat-protocol/frames.d.ts +213 -0
- package/dist/chat-protocol/frames.d.ts.map +1 -0
- package/dist/chat-protocol/index.cjs +506 -0
- package/dist/chat-protocol/index.cjs.map +1 -0
- package/dist/chat-protocol/index.d.ts +18 -0
- package/dist/chat-protocol/index.d.ts.map +1 -0
- package/dist/chat-protocol/index.js +490 -0
- package/dist/chat-protocol/index.js.map +1 -0
- package/dist/chat-protocol/ip-normalize.d.ts +44 -0
- package/dist/chat-protocol/ip-normalize.d.ts.map +1 -0
- package/dist/chat-protocol/nats-decoder.d.ts +26 -0
- package/dist/chat-protocol/nats-decoder.d.ts.map +1 -0
- package/dist/{chunk-3SQ5KXHQ.cjs → chunk-2T4GTV25.cjs} +9 -9
- package/dist/{chunk-3SQ5KXHQ.cjs.map → chunk-2T4GTV25.cjs.map} +1 -1
- package/dist/{chunk-CWAOV2FK.cjs → chunk-3CGZPAGR.cjs} +3 -3
- package/dist/{chunk-CWAOV2FK.cjs.map → chunk-3CGZPAGR.cjs.map} +1 -1
- package/dist/{chunk-TLMJHMXJ.js → chunk-3QSR22IC.js} +12 -12
- package/dist/chunk-3QSR22IC.js.map +1 -0
- package/dist/{chunk-TWYNR4TZ.cjs → chunk-4G5TLHJD.cjs} +7141 -4799
- package/dist/chunk-4G5TLHJD.cjs.map +1 -0
- package/dist/{chunk-ADPMHWOE.js → chunk-72XAID7Y.js} +4 -4
- package/dist/{chunk-PAGKRNWK.js → chunk-7WZHBQ4J.js} +2 -2
- package/dist/{chunk-OCEKO5CW.js → chunk-AEELJC4N.js} +12106 -9764
- package/dist/chunk-AEELJC4N.js.map +1 -0
- package/dist/{chunk-Z42BGM6Q.cjs → chunk-BT2WWDFP.cjs} +5 -5
- package/dist/{chunk-Z42BGM6Q.cjs.map → chunk-BT2WWDFP.cjs.map} +1 -1
- package/dist/{chunk-7LEL3RIX.cjs → chunk-C7OY3PQP.cjs} +11 -11
- package/dist/{chunk-7LEL3RIX.cjs.map → chunk-C7OY3PQP.cjs.map} +1 -1
- package/dist/{chunk-RHGGEKPQ.cjs → chunk-CIOLOQKQ.cjs} +4 -4
- package/dist/{chunk-RHGGEKPQ.cjs.map → chunk-CIOLOQKQ.cjs.map} +1 -1
- package/dist/{chunk-TSZHM74B.js → chunk-DC2TKS7C.js} +2 -2
- package/dist/{chunk-M2GOR3XQ.cjs → chunk-DYPYR7FR.cjs} +87 -87
- package/dist/{chunk-M2GOR3XQ.cjs.map → chunk-DYPYR7FR.cjs.map} +1 -1
- package/dist/{chunk-I64ABCDX.js → chunk-I2B6X77L.js} +2 -2
- package/dist/{chunk-NIZDKTGL.cjs → chunk-K5MSCMDK.cjs} +37 -37
- package/dist/{chunk-NIZDKTGL.cjs.map → chunk-K5MSCMDK.cjs.map} +1 -1
- package/dist/{chunk-DTYRYB2N.js → chunk-K6QTZ7CZ.js} +2 -2
- package/dist/{chunk-4LTMXDUS.js → chunk-KBN7PMFT.js} +2 -2
- package/dist/{chunk-TBMV7I5N.js → chunk-KXZO2WZX.js} +2 -2
- package/dist/{chunk-QTYZMP6D.cjs → chunk-LBAKLT6T.cjs} +62 -62
- package/dist/chunk-LBAKLT6T.cjs.map +1 -0
- package/dist/{chunk-KEBYLU3U.js → chunk-LFUPI7VX.js} +2 -2
- package/dist/{chunk-LDTR4IVZ.cjs → chunk-M37PBG4N.cjs} +31 -31
- package/dist/{chunk-LDTR4IVZ.cjs.map → chunk-M37PBG4N.cjs.map} +1 -1
- package/dist/{chunk-WA7RR64F.js → chunk-PO5O654H.js} +6 -5
- package/dist/chunk-PO5O654H.js.map +1 -0
- package/dist/{chunk-WK4N5VBX.cjs → chunk-QJJISLPA.cjs} +28 -27
- package/dist/chunk-QJJISLPA.cjs.map +1 -0
- package/dist/{chunk-2F44PLTV.cjs → chunk-T7MCSA55.cjs} +26 -26
- package/dist/{chunk-2F44PLTV.cjs.map → chunk-T7MCSA55.cjs.map} +1 -1
- package/dist/{chunk-WJQHJD7J.js → chunk-TWSKTJHW.js} +2 -2
- package/dist/{chunk-ZSQHZYCO.cjs → chunk-UQDMJ6DH.cjs} +13 -13
- package/dist/{chunk-ZSQHZYCO.cjs.map → chunk-UQDMJ6DH.cjs.map} +1 -1
- package/dist/{chunk-TZRUCD56.js → chunk-V3ZAAFE3.js} +5 -5
- package/dist/{chunk-LRGHJPET.js → chunk-XGIFOHKE.js} +2 -2
- package/dist/{chunk-POOMO3PA.cjs → chunk-YQEPRYT5.cjs} +7 -7
- package/dist/{chunk-POOMO3PA.cjs.map → chunk-YQEPRYT5.cjs.map} +1 -1
- package/dist/components/case-studies/index.cjs +8 -8
- package/dist/components/case-studies/index.js +2 -2
- package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
- package/dist/components/chat/chat-message-list.d.ts.map +1 -1
- package/dist/components/chat/hooks/index.d.ts +0 -1
- package/dist/components/chat/hooks/index.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-chat.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-chunk-catchup.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +15 -48
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +10 -57
- package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +10 -2
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.d.ts +1 -0
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +21 -13
- package/dist/components/chat/stream/chat-dialog-store.d.ts +184 -0
- package/dist/components/chat/stream/chat-dialog-store.d.ts.map +1 -0
- package/dist/components/chat/stream/chat-stream-reducer.d.ts +380 -0
- package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +1 -0
- package/dist/components/chat/stream/delta-batcher.d.ts +51 -0
- package/dist/components/chat/stream/delta-batcher.d.ts.map +1 -0
- package/dist/components/chat/stream/index.d.ts +17 -0
- package/dist/components/chat/stream/index.d.ts.map +1 -0
- package/dist/components/chat/stream/message-mutations.d.ts +77 -0
- package/dist/components/chat/stream/message-mutations.d.ts.map +1 -0
- package/dist/components/chat/stream/use-chat-stream-reducer.d.ts +22 -0
- package/dist/components/chat/stream/use-chat-stream-reducer.d.ts.map +1 -0
- package/dist/components/chat/types/api.types.d.ts +1 -81
- package/dist/components/chat/types/api.types.d.ts.map +1 -1
- package/dist/components/chat/types/processing.types.d.ts +2 -93
- package/dist/components/chat/types/processing.types.d.ts.map +1 -1
- package/dist/components/chat/types/unified-chat-state.types.d.ts +15 -0
- package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
- package/dist/components/chat/utils/extract-incomplete-message-state.d.ts +34 -6
- package/dist/components/chat/utils/extract-incomplete-message-state.d.ts.map +1 -1
- package/dist/components/chat/utils/history-merge.d.ts.map +1 -1
- package/dist/components/chat/utils/index.d.ts +2 -3
- package/dist/components/chat/utils/index.d.ts.map +1 -1
- package/dist/components/chat/utils/process-historical-messages.d.ts +59 -11
- package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/docs/index.cjs +5 -5
- package/dist/components/docs/index.js +4 -4
- package/dist/components/embeds/index.cjs +3 -3
- package/dist/components/embeds/index.js +2 -2
- package/dist/components/faq/index.cjs +3 -3
- package/dist/components/faq/index.js +2 -2
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/help-center-pages/index.cjs +22 -22
- package/dist/components/help-center-pages/index.js +13 -13
- package/dist/components/index.cjs +174 -132
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +65 -23
- package/dist/components/index.js.map +1 -1
- package/dist/components/meeting-scheduler/index.cjs +34 -34
- package/dist/components/meeting-scheduler/index.js +3 -3
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/onboarding-guides/index.cjs +5 -5
- package/dist/components/onboarding-guides/index.js +4 -4
- package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
- package/dist/components/tickets/index.cjs +6 -6
- package/dist/components/tickets/index.js +5 -5
- package/dist/components/ui/index.cjs +44 -2
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.ts +1 -2
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +55 -13
- package/dist/components/ui/markdown/base-components.d.ts +51 -0
- package/dist/components/ui/markdown/base-components.d.ts.map +1 -0
- package/dist/components/ui/markdown/engine.d.ts +99 -0
- package/dist/components/ui/markdown/engine.d.ts.map +1 -0
- package/dist/components/ui/markdown/heading-ids.d.ts +65 -0
- package/dist/components/ui/markdown/heading-ids.d.ts.map +1 -0
- package/dist/components/ui/markdown/index.d.ts +18 -0
- package/dist/components/ui/markdown/index.d.ts.map +1 -0
- package/dist/components/ui/markdown/mermaid-diagram.d.ts +79 -0
- package/dist/components/ui/markdown/mermaid-diagram.d.ts.map +1 -0
- package/dist/components/ui/markdown/rich/embed-overrides.d.ts +14 -0
- package/dist/components/ui/markdown/rich/embed-overrides.d.ts.map +1 -0
- package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts +40 -0
- package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts.map +1 -0
- package/dist/components/ui/markdown/rich/shortcodes.d.ts +8 -0
- package/dist/components/ui/markdown/rich/shortcodes.d.ts.map +1 -0
- package/dist/components/ui/markdown/sanitize.d.ts +153 -0
- package/dist/components/ui/markdown/sanitize.d.ts.map +1 -0
- package/dist/components/ui/markdown/simple-markdown-renderer.d.ts +23 -0
- package/dist/components/ui/markdown/simple-markdown-renderer.d.ts.map +1 -0
- package/dist/components/ui/markdown/streaming.d.ts +78 -0
- package/dist/components/ui/markdown/streaming.d.ts.map +1 -0
- package/dist/components/ui/markdown/text-size.d.ts +34 -0
- package/dist/components/ui/markdown/text-size.d.ts.map +1 -0
- package/dist/index.cjs +60 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +71 -13
- package/dist/utils/index.cjs +169 -40
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +162 -41
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/markdown-fences.d.ts +42 -0
- package/dist/utils/markdown-fences.d.ts.map +1 -0
- package/dist/utils/markdown-heading-id.d.ts +85 -0
- package/dist/utils/markdown-heading-id.d.ts.map +1 -0
- package/dist/utils/markdown-section-extractor.d.ts.map +1 -1
- package/package.json +7 -1
- package/src/chat-protocol/__tests__/__snapshots__/nats-decoder-golden.test.ts.snap +319 -0
- package/src/chat-protocol/__tests__/chat-protocol.test.ts +516 -0
- package/src/chat-protocol/__tests__/env-flag.test.ts +52 -0
- package/src/chat-protocol/__tests__/ip-normalize.test.ts +136 -0
- package/src/chat-protocol/__tests__/nats-decoder-golden.test.ts +237 -0
- package/src/chat-protocol/decode.ts +278 -0
- package/src/chat-protocol/encode.ts +71 -0
- package/src/chat-protocol/env-flag.ts +39 -0
- package/src/chat-protocol/events.ts +254 -0
- package/src/chat-protocol/frames.ts +245 -0
- package/src/chat-protocol/index.ts +21 -0
- package/src/chat-protocol/ip-normalize.ts +146 -0
- package/src/chat-protocol/nats-decoder.ts +264 -0
- package/src/components/chat/.chat-message-list.md +10 -6
- package/src/components/chat/__tests__/chat-message-list.test.tsx +450 -9
- package/src/components/chat/__tests__/chat-message-streaming-memo.test.tsx +207 -0
- package/src/components/chat/__tests__/chat-pending-turn.test.tsx +250 -0
- package/src/components/chat/chat-message-enhanced.tsx +122 -20
- package/src/components/chat/chat-message-list.tsx +515 -133
- package/src/components/chat/embeddable-chat.tsx +6 -0
- package/src/components/chat/hooks/.index.md +30 -33
- package/src/components/chat/hooks/.use-nats-chat-adapter.md +36 -55
- package/src/components/chat/hooks/__tests__/__snapshots__/conversation-id-persistence-golden.test.ts.snap +37 -0
- package/src/components/chat/hooks/__tests__/__snapshots__/sse-stream-golden.test.ts.snap +0 -0
- package/src/components/chat/hooks/__tests__/chunk-catchup-dialog-staleness.test.ts +92 -0
- package/src/components/chat/hooks/__tests__/conversation-id-persistence-golden.test.ts +438 -0
- package/src/components/chat/hooks/__tests__/sse-stream-golden.test.ts +318 -0
- package/src/components/chat/hooks/index.ts +0 -1
- package/src/components/chat/hooks/use-chat.ts +8 -0
- package/src/components/chat/hooks/use-chunk-catchup.ts +26 -1
- package/src/components/chat/hooks/use-nats-chat-adapter.ts +254 -825
- package/src/components/chat/hooks/use-sse-chat-adapter.ts +380 -684
- package/src/components/chat/index.ts +5 -0
- package/src/components/chat/stream/__tests__/__snapshots__/chat-stream-reducer-golden.test.ts.snap +944 -0
- package/src/components/chat/stream/__tests__/chat-dialog-store.test.ts +806 -0
- package/src/components/chat/stream/__tests__/chat-stream-reducer-golden.test.ts +467 -0
- package/src/components/chat/stream/__tests__/chat-stream-reducer.test.ts +1330 -0
- package/src/components/chat/stream/__tests__/delta-batcher.test.ts +255 -0
- package/src/components/chat/stream/__tests__/use-chat-stream-reducer.test.ts +105 -0
- package/src/components/chat/stream/chat-dialog-store.ts +536 -0
- package/src/components/chat/stream/chat-stream-reducer.ts +1928 -0
- package/src/components/chat/stream/delta-batcher.ts +168 -0
- package/src/components/chat/stream/index.ts +55 -0
- package/src/components/chat/stream/message-mutations.ts +340 -0
- package/src/components/chat/stream/use-chat-stream-reducer.ts +126 -0
- package/src/components/chat/thinking-display.tsx +1 -1
- package/src/components/chat/types/.api.types.md +39 -49
- package/src/components/chat/types/.processing.types.md +29 -58
- package/src/components/chat/types/.unified-chat-state.types.md +2 -2
- package/src/components/chat/types/api.types.ts +6 -73
- package/src/components/chat/types/processing.types.ts +11 -53
- package/src/components/chat/types/unified-chat-state.types.ts +16 -0
- package/src/components/chat/utils/.extract-incomplete-message-state.md +21 -3
- package/src/components/chat/utils/.history-merge.md +44 -3
- package/src/components/chat/utils/.index.md +31 -40
- package/src/components/chat/utils/__tests__/__snapshots__/process-historical-messages-golden.test.ts.snap +420 -0
- package/src/components/chat/utils/__tests__/__snapshots__/segment-accumulator-golden.test.ts.snap +605 -0
- package/src/components/chat/utils/__tests__/extract-incomplete-message-state.test.ts +106 -0
- package/src/components/chat/utils/__tests__/history-merge.test.ts +160 -0
- package/src/components/chat/utils/__tests__/process-historical-messages-approvals.test.ts +61 -0
- package/src/components/chat/utils/__tests__/process-historical-messages-golden.test.ts +394 -0
- package/src/components/chat/utils/__tests__/segment-accumulator-golden.test.ts +270 -0
- package/src/components/chat/utils/extract-incomplete-message-state.ts +93 -6
- package/src/components/chat/utils/history-merge.ts +85 -5
- package/src/components/chat/utils/index.ts +5 -8
- package/src/components/chat/utils/process-historical-messages.ts +361 -385
- package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +22 -4
- package/src/components/shared/legal-document/legal-document-page.tsx +1 -1
- package/src/components/shared/product-release/release-detail-page.tsx +19 -4
- package/src/components/ui/__tests__/__snapshots__/markdown-parity.test.tsx.snap +2420 -0
- package/src/components/ui/__tests__/markdown-parity.test.tsx +2540 -0
- package/src/components/ui/index.ts +1 -2
- package/src/components/ui/markdown/__tests__/mermaid-security.test.ts +176 -0
- package/src/components/ui/markdown/__tests__/mermaid-stale-render.test.tsx +151 -0
- package/src/components/ui/markdown/__tests__/sanitize-invariant.test.ts +354 -0
- package/src/components/ui/markdown/__tests__/sanitize-render.test.tsx +118 -0
- package/src/components/ui/markdown/__tests__/streaming.test.tsx +436 -0
- package/src/components/ui/markdown/base-components.tsx +360 -0
- package/src/components/ui/markdown/engine.tsx +315 -0
- package/src/components/ui/markdown/heading-ids.ts +239 -0
- package/src/components/ui/markdown/index.ts +49 -0
- package/src/components/ui/markdown/mermaid-diagram.tsx +323 -0
- package/src/components/ui/markdown/rich/embed-overrides.tsx +199 -0
- package/src/components/ui/markdown/rich/rich-markdown-renderer.tsx +184 -0
- package/src/components/ui/markdown/rich/shortcodes.ts +170 -0
- package/src/components/ui/markdown/sanitize.ts +3584 -0
- package/src/components/ui/markdown/simple-markdown-renderer.tsx +28 -0
- package/src/components/ui/markdown/streaming.ts +390 -0
- package/src/components/ui/markdown/text-size.ts +106 -0
- package/src/components/ui/release-changelog-section.tsx +1 -1
- package/src/components/ui/ticket-info-section.tsx +1 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/markdown-fences.ts +127 -0
- package/src/utils/markdown-heading-id.ts +348 -0
- package/src/utils/markdown-section-extractor.ts +41 -56
- package/dist/chunk-OCEKO5CW.js.map +0 -1
- package/dist/chunk-QTYZMP6D.cjs.map +0 -1
- package/dist/chunk-TLMJHMXJ.js.map +0 -1
- package/dist/chunk-TWYNR4TZ.cjs.map +0 -1
- package/dist/chunk-WA7RR64F.js.map +0 -1
- package/dist/chunk-WK4N5VBX.cjs.map +0 -1
- package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts +0 -6
- package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +0 -1
- package/dist/components/chat/utils/chunk-parser.d.ts +0 -25
- package/dist/components/chat/utils/chunk-parser.d.ts.map +0 -1
- package/dist/components/ui/rich-markdown-renderer.d.ts +0 -34
- package/dist/components/ui/rich-markdown-renderer.d.ts.map +0 -1
- package/dist/components/ui/simple-markdown-renderer.d.ts +0 -73
- package/dist/components/ui/simple-markdown-renderer.d.ts.map +0 -1
- package/src/components/chat/hooks/.use-realtime-chunk-processor.md +0 -77
- package/src/components/chat/hooks/use-realtime-chunk-processor.ts +0 -489
- package/src/components/chat/utils/.chunk-parser.md +0 -62
- package/src/components/chat/utils/chunk-parser.ts +0 -262
- package/src/components/ui/.simple-markdown-renderer.md +0 -52
- package/src/components/ui/rich-markdown-renderer.tsx +0 -1223
- package/src/components/ui/simple-markdown-renderer.tsx +0 -964
- /package/dist/{chunk-ADPMHWOE.js.map → chunk-72XAID7Y.js.map} +0 -0
- /package/dist/{chunk-PAGKRNWK.js.map → chunk-7WZHBQ4J.js.map} +0 -0
- /package/dist/{chunk-TSZHM74B.js.map → chunk-DC2TKS7C.js.map} +0 -0
- /package/dist/{chunk-I64ABCDX.js.map → chunk-I2B6X77L.js.map} +0 -0
- /package/dist/{chunk-DTYRYB2N.js.map → chunk-K6QTZ7CZ.js.map} +0 -0
- /package/dist/{chunk-4LTMXDUS.js.map → chunk-KBN7PMFT.js.map} +0 -0
- /package/dist/{chunk-TBMV7I5N.js.map → chunk-KXZO2WZX.js.map} +0 -0
- /package/dist/{chunk-KEBYLU3U.js.map → chunk-LFUPI7VX.js.map} +0 -0
- /package/dist/{chunk-WJQHJD7J.js.map → chunk-TWSKTJHW.js.map} +0 -0
- /package/dist/{chunk-TZRUCD56.js.map → chunk-V3ZAAFE3.js.map} +0 -0
- /package/dist/{chunk-LRGHJPET.js.map → chunk-XGIFOHKE.js.map} +0 -0
|
@@ -1531,6 +1531,12 @@ function EmbeddableChatInner({
|
|
|
1531
1531
|
content: m.segments && m.segments.length > 0 ? m.segments : m.content,
|
|
1532
1532
|
timestamp,
|
|
1533
1533
|
assistantType: m.role === 'assistant' ? ('mingo' as const) : undefined,
|
|
1534
|
+
// `hidden` is load-bearing, NOT cosmetic: it carries synthetic rows
|
|
1535
|
+
// (e.g. an auto-continuation directive) that the LLM must see but the
|
|
1536
|
+
// reader must not. Dropping it here made the raw directive text render
|
|
1537
|
+
// as an ordinary bubble. This field-by-field rebuild has to forward it
|
|
1538
|
+
// explicitly — see `Message.hidden` and `chat-message-list`'s skip.
|
|
1539
|
+
...(m.hidden ? { hidden: true } : {}),
|
|
1534
1540
|
...(m.chatRefs ? { chatRefs: m.chatRefs } : {}),
|
|
1535
1541
|
...(m.scrollAnchor ? { scrollAnchor: m.scrollAnchor } : {}),
|
|
1536
1542
|
// Forward attached context items so the user bubble renders its chips.
|
|
@@ -1,49 +1,46 @@
|
|
|
1
|
-
<!-- source-hash:
|
|
2
|
-
Barrel export file
|
|
1
|
+
<!-- source-hash: d1cebe46eff04115f214c16b75a69467 -->
|
|
2
|
+
Barrel export file for the chat hooks module, re-exporting all public hooks from their individual files into a single `'use client'` entry point.
|
|
3
3
|
|
|
4
4
|
## Key Components
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- **`useChat`** / **`useSSE`** — Core chat and Server-Sent Events hooks (ported from hub, without `MockChatService`/`useChatConfig`)
|
|
15
|
-
- **`useSlashCommands`** — Slash command parsing and dispatch
|
|
16
|
-
- **`useEmptyStateConfig`** — Empty state configuration
|
|
17
|
-
- **`useChatAttachments`** / **`useChatAttachmentImageGallery`** — File attachment handling and image gallery
|
|
18
|
-
- **`useChatIdentity`** — Chat user/agent identity resolution
|
|
19
|
-
- **`useChatCardItem`** — Chat card rendering state
|
|
20
|
-
- **`useCloseOnNavigation`** — Dismisses dialogs/panels on route change
|
|
21
|
-
|
|
22
|
-
### Unified Chat Surface
|
|
23
|
-
- **`useUnifiedChat`** — Primary public hook; selects transport by `activeMode`
|
|
24
|
-
- **`useSSEChatAdapter`** / **`useNatsChatAdapter`** — Transport adapters (SSE and NATS)
|
|
25
|
-
- **`useEmbeddedChat`** — Legacy SSE alias for embedded surfaces
|
|
26
|
-
|
|
27
|
-
### Utilities
|
|
28
|
-
- **`useProxiedImageUrl`** — Resolves proxied image URLs from `ChatRuntime.endpoints`
|
|
6
|
+
| Export Group | Hooks |
|
|
7
|
+
|---|---|
|
|
8
|
+
| **Realtime / Streaming** | `useChunkCatchup`, `useJetstreamDialogSubscription`, `useNatsDialogSubscription` |
|
|
9
|
+
| **UI Utilities** | `useCollapsible`, `useCloseOnNavigation`, `useChatCardItem` |
|
|
10
|
+
| **Chat Core** | `useChat`, `useSSE`, `useChatIdentity`, `useChatAttachments`, `useChatAttachmentImageGallery`, `useSlashCommands` |
|
|
11
|
+
| **Transport Adapters** | `useSSEChatAdapter`, `useNatsChatAdapter` |
|
|
12
|
+
| **Unified Surface** | `useUnifiedChat` (primary), `useEmbeddedChat` (legacy SSE alias) |
|
|
13
|
+
| **Image Proxy** | `useProxiedImageUrl` |
|
|
29
14
|
|
|
30
15
|
## Usage Example
|
|
31
16
|
|
|
32
17
|
```typescript
|
|
33
|
-
//
|
|
18
|
+
// Typical consumer — import directly from the module index
|
|
34
19
|
import {
|
|
35
20
|
useUnifiedChat,
|
|
36
21
|
useChatAttachments,
|
|
37
|
-
|
|
38
|
-
} from '@
|
|
22
|
+
useSlashCommands,
|
|
23
|
+
} from '@flamingo/chat-hooks'
|
|
39
24
|
|
|
40
25
|
function ChatPanel({ modes, activeMode }) {
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
26
|
+
const chat = useUnifiedChat({ modes, activeMode })
|
|
27
|
+
const attachments = useChatAttachments()
|
|
28
|
+
const slashCommands = useSlashCommands()
|
|
44
29
|
|
|
45
|
-
|
|
30
|
+
// ...
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Advanced: direct transport access
|
|
34
|
+
import { useNatsChatAdapter } from '@flamingo/chat-hooks'
|
|
35
|
+
|
|
36
|
+
function CustomTransportPanel() {
|
|
37
|
+
const nats = useNatsChatAdapter({ /* config */ })
|
|
38
|
+
// ...
|
|
46
39
|
}
|
|
47
40
|
```
|
|
48
41
|
|
|
49
|
-
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
- Marked `'use client'` — safe for React Server Component trees; hooks run only on the client.
|
|
45
|
+
- `useUnifiedChat` is the recommended entry point for new consumers; `useEmbeddedChat` is the legacy SSE alias kept for backward compatibility.
|
|
46
|
+
- `useProxiedImageUrl` reads proxy config from `ChatRuntime.endpoints`, keeping image-proxy resolution consistent between hub and embedder environments.
|
|
@@ -1,71 +1,52 @@
|
|
|
1
|
-
<!-- source-hash:
|
|
2
|
-
|
|
1
|
+
<!-- source-hash: 6c5780e92306ea381bac35aaf97c435f -->
|
|
2
|
+
Provides the NATS/Mingo-mode transport adapter for the unified chat surface, implementing the `UnifiedChatState` contract so the `useChat({ mode })` dispatcher can switch between NATS and SSE adapters without shell-side branching.
|
|
3
3
|
|
|
4
4
|
## Key Components
|
|
5
5
|
|
|
6
6
|
### `UseNatsChatAdapterConfig`
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
Consumer-supplied configuration interface covering:
|
|
8
|
+
- `dialogId` — active conversation identifier
|
|
9
|
+
- `getNatsWsUrl` — factory returning the NATS WebSocket URL
|
|
10
|
+
- `publishUserMessage` — consumer-owned send callback (HTTP POST or NATS publish)
|
|
11
|
+
- `fetchChunks` — optional historical chunk fetcher for catchup
|
|
12
|
+
- `clientConfig` — optional NATS auth credentials
|
|
13
|
+
- `enableThinking` / `batchApprovalsEnabled` — processor feature flags
|
|
10
14
|
|
|
11
|
-
###
|
|
15
|
+
### `UseNatsChatAdapterOptions`
|
|
16
|
+
- `active` — gates the live subscription; keeps message state alive while the mode is hidden
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
| `getNatsWsUrl` | ✅ | Returns the NATS WebSocket URL or `null` to suspend |
|
|
16
|
-
| `publishUserMessage` | ✅ | Consumer-owned send callback (HTTP POST or NATS publish) |
|
|
17
|
-
| `dialogId` | ❌ | Explicit dialog ID (bare-transport mode) |
|
|
18
|
-
| `fetchDialogs` | ❌ | Enables managed-dialog mode with sidebar support |
|
|
19
|
-
| `fetchDialogMessages` | ❌ | Populates history on dialog switch |
|
|
20
|
-
| `topics` | ❌ | NATS subject suffixes to tail (default: `['message']`) |
|
|
21
|
-
|
|
22
|
-
### Supporting Interfaces
|
|
23
|
-
|
|
24
|
-
- **`FetchDialogsParams`** / **`FetchDialogsResult`** — paginated dialog list with cursor-based pagination
|
|
25
|
-
- **`FetchDialogMessagesParams`** / **`FetchDialogMessagesResult`** — paginated message history with optional `tokenUsage`
|
|
26
|
-
|
|
27
|
-
### Composition Stack
|
|
18
|
+
### `useNatsChatAdapter(config, options)`
|
|
19
|
+
Main hook. Composes three internal hooks:
|
|
28
20
|
|
|
29
21
|
```text
|
|
30
|
-
useNatsDialogSubscription →
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
useChunkCatchup →
|
|
35
|
-
↓
|
|
36
|
-
config.publishUserMessage → consumer-owned send (HTTP/NATS)
|
|
22
|
+
useNatsDialogSubscription → live NATS event tail
|
|
23
|
+
↓
|
|
24
|
+
decodeNatsChunk + reducer → chunk → ChatStreamEvent → state
|
|
25
|
+
↓
|
|
26
|
+
useChunkCatchup → back-fills missed chunks on reconnect/activation
|
|
37
27
|
```
|
|
38
28
|
|
|
29
|
+
Returns a full `UnifiedChatState` object including `messages`, `isLoading`, `streamingPhase`, `sendMessage`, `stopMessage`, and `clearMessages`.
|
|
30
|
+
|
|
39
31
|
## Usage Example
|
|
40
32
|
|
|
41
33
|
```typescript
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
34
|
+
const chatState = useNatsChatAdapter(
|
|
35
|
+
{
|
|
36
|
+
dialogId: 'dialog-abc123',
|
|
37
|
+
getNatsWsUrl: () => `wss://nats.example.com`,
|
|
38
|
+
publishUserMessage: async (text, { dialogId }) => {
|
|
39
|
+
await fetch('/api/chat', {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
body: JSON.stringify({ text, dialogId }),
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
fetchChunks: ({ dialogId, after }) =>
|
|
45
|
+
fetch(`/api/chunks?dialogId=${dialogId}&after=${after}`).then(r => r.json()),
|
|
46
|
+
batchApprovalsEnabled: true,
|
|
51
47
|
},
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// Managed-dialog mode (openframe-frontend / EmbeddableChat)
|
|
56
|
-
const chatState = useNatsChatAdapter({
|
|
57
|
-
getNatsWsUrl: () => natsUrl,
|
|
58
|
-
publishUserMessage: sendMessage,
|
|
59
|
-
fetchDialogs: async ({ cursor, limit }) => api.listDialogs({ cursor, limit }),
|
|
60
|
-
fetchDialogMessages: async ({ dialogId, cursor }) =>
|
|
61
|
-
api.getMessages(dialogId, { cursor }),
|
|
62
|
-
createDialog: () => api.createDialog(),
|
|
63
|
-
deleteDialog: (id) => api.deleteDialog(id),
|
|
64
|
-
approveRequest: (requestId) => api.approve(requestId),
|
|
65
|
-
rejectRequest: (requestId, reason) => api.reject(requestId, reason),
|
|
66
|
-
})
|
|
48
|
+
{ active: isNatsModeVisible },
|
|
49
|
+
)
|
|
67
50
|
```
|
|
68
51
|
|
|
69
|
-
> **Note:**
|
|
70
|
-
|
|
71
|
-
**Source:** [`use-nats-chat-adapter.ts`](https://github.com/flamingo-stack/openframe-oss-lib/blob/main/use-nats-chat-adapter.ts)
|
|
52
|
+
> **Note:** `publishUserMessage` is intentionally consumer-owned — the adapter only handles optimistic UI updates and phase transitions; the actual transport is wired externally.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`server-history hydration (materializes through the reducer) > rebuilds messages + sendIdx-keyed refs + send counter from the transcript 1`] = `
|
|
4
|
+
[
|
|
5
|
+
{
|
|
6
|
+
"content": "open a ticket for the broken printer",
|
|
7
|
+
"id": "hydrated-1",
|
|
8
|
+
"role": "user",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"chatRefs": {
|
|
12
|
+
"ticket:77": {
|
|
13
|
+
"id": "77",
|
|
14
|
+
"metadata": {
|
|
15
|
+
"status": "OPEN",
|
|
16
|
+
},
|
|
17
|
+
"title": "Broken printer",
|
|
18
|
+
"type": "ticket",
|
|
19
|
+
"url": null,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
"content": "✅ Approved — ticket created: [card://ticket:77]",
|
|
23
|
+
"id": "hydrated-2",
|
|
24
|
+
"role": "assistant",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"content": "what is the pricing?",
|
|
28
|
+
"id": "hydrated-3",
|
|
29
|
+
"role": "user",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"content": "Pricing starts at $99/month per site.",
|
|
33
|
+
"id": "hydrated-4",
|
|
34
|
+
"role": "assistant",
|
|
35
|
+
},
|
|
36
|
+
]
|
|
37
|
+
`;
|
|
Binary file
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A catch-up fetch is async and the active dialog can change while it is in
|
|
3
|
+
* flight — switching dialogs is the ordinary interaction, not an edge case.
|
|
4
|
+
*
|
|
5
|
+
* `useChunkCatchup` already knows about staleness, but only in its `finally`:
|
|
6
|
+
* the processing loop ran FIRST and unconditionally. Everything downstream of
|
|
7
|
+
* it is bound to the CURRENT dialog — `onChunkReceived` is read through a ref
|
|
8
|
+
* the adapter reassigns every render, and the seq bookkeeping refs were just
|
|
9
|
+
* re-armed by `resetChunkTracking` for the newly-entered dialog — so a fetch
|
|
10
|
+
* that resolved late wrote dialog A's transcript into dialog B, and pushed B's
|
|
11
|
+
* seq cursor to A's JetStream sequence. Since the reducer drops anything at or
|
|
12
|
+
* below `lastAppliedSeq`, and A's stream position is unrelated to B's, that can
|
|
13
|
+
* silently discard B's own live chunks for the rest of the session.
|
|
14
|
+
*
|
|
15
|
+
* The same applies to the flags: finalizing `hasCompletedInitialCatchup` /
|
|
16
|
+
* `bufferUntilInitialCatchupComplete` on a stale fetch ends the NEW dialog's
|
|
17
|
+
* buffering window early, and draining `chunkBuffer` hands B's buffered live
|
|
18
|
+
* deliveries to A's stale batch.
|
|
19
|
+
*/
|
|
20
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
21
|
+
import { renderHook, act } from '@testing-library/react'
|
|
22
|
+
import { useChunkCatchup } from '../use-chunk-catchup'
|
|
23
|
+
import type { ChunkData } from '../../types'
|
|
24
|
+
|
|
25
|
+
type Deferred = {
|
|
26
|
+
promise: Promise<ChunkData[]>
|
|
27
|
+
resolve: (chunks: ChunkData[]) => void
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function deferred(): Deferred {
|
|
31
|
+
let resolve!: (chunks: ChunkData[]) => void
|
|
32
|
+
const promise = new Promise<ChunkData[]>((r) => {
|
|
33
|
+
resolve = r
|
|
34
|
+
})
|
|
35
|
+
return { promise, resolve }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const textChunk = (text: string, streamSeq: number, sequenceId: number): ChunkData =>
|
|
39
|
+
({ type: 'TEXT', text, streamSeq, sequenceId }) as unknown as ChunkData
|
|
40
|
+
|
|
41
|
+
describe('useChunkCatchup — dialog staleness', () => {
|
|
42
|
+
it('does not deliver a catchup that resolved after the dialog changed', async () => {
|
|
43
|
+
const onChunkReceived = vi.fn()
|
|
44
|
+
const pending = deferred()
|
|
45
|
+
const fetchChunks = vi.fn((dialogId: string) =>
|
|
46
|
+
dialogId === 'A' ? pending.promise : Promise.resolve([]),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
const { result, rerender } = renderHook(
|
|
50
|
+
({ dialogId }: { dialogId: string }) =>
|
|
51
|
+
useChunkCatchup({ dialogId, onChunkReceived, fetchChunks }),
|
|
52
|
+
{ initialProps: { dialogId: 'A' } },
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
// Dialog A starts its catch-up…
|
|
56
|
+
let catchup!: Promise<unknown>
|
|
57
|
+
await act(async () => {
|
|
58
|
+
catchup = result.current.catchUpChunks()
|
|
59
|
+
})
|
|
60
|
+
expect(fetchChunks).toHaveBeenCalledWith('A', expect.anything(), undefined)
|
|
61
|
+
|
|
62
|
+
// …the user switches to B while A's fetch is still open…
|
|
63
|
+
rerender({ dialogId: 'B' })
|
|
64
|
+
|
|
65
|
+
// …and only then does A's fetch land, carrying A's own transcript.
|
|
66
|
+
await act(async () => {
|
|
67
|
+
pending.resolve([textChunk('SECRET FROM DIALOG A', 100001, 100001)])
|
|
68
|
+
await catchup
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
expect(onChunkReceived).not.toHaveBeenCalled()
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('still delivers a catchup for the dialog that is current when it lands', () => {
|
|
75
|
+
const onChunkReceived = vi.fn()
|
|
76
|
+
const fetchChunks = vi.fn(() =>
|
|
77
|
+
Promise.resolve([textChunk('B REAL CONTENT', 50001, 50001)]),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
const { result } = renderHook(() =>
|
|
81
|
+
useChunkCatchup({ dialogId: 'B', onChunkReceived, fetchChunks }),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return act(async () => {
|
|
85
|
+
await result.current.catchUpChunks()
|
|
86
|
+
}).then(() => {
|
|
87
|
+
// Positive control: the guard must not swallow the normal path.
|
|
88
|
+
expect(onChunkReceived).toHaveBeenCalledTimes(1)
|
|
89
|
+
expect(onChunkReceived.mock.calls[0][0]).toMatchObject({ text: 'B REAL CONTENT' })
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
})
|