@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
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createChatStreamReducer — THE master chat-stream reader (Phase 3 of the
|
|
3
|
+
* chat unification). One accumulation path for every event source:
|
|
4
|
+
*
|
|
5
|
+
* SSE bytes → createSseFrameDecoder ─┐
|
|
6
|
+
* NATS chunk → decodeNatsChunk ─┼→ ChatStreamEvent → reducer.apply()
|
|
7
|
+
* history → decodeHistoricalMessageData (per-item vocabulary) →
|
|
8
|
+
* envelope grouping → reducer.initializeWithState()
|
|
9
|
+
*
|
|
10
|
+
* The reducer absorbs, verbatim, the semantics that used to be spread over
|
|
11
|
+
* three layers:
|
|
12
|
+
* - `MessageSegmentAccumulator` stays as the internal per-turn segment
|
|
13
|
+
* kernel (instantiated here — its goldens remain valid);
|
|
14
|
+
* - the deleted `useRealtimeChunkProcessor`'s switch (in-stream vs post-END
|
|
15
|
+
* routing, agent-busy outside a message window, escalated approvals,
|
|
16
|
+
* compaction upsert, direct-mode barrier) — surfaced as
|
|
17
|
+
* `ChatReducerEffect`s for consumers that want the callback contract;
|
|
18
|
+
* - `useNatsChatAdapter`'s message-mutation callbacks (trailing-assistant
|
|
19
|
+
* replace/append, compaction upsert, cross-message tool merge, approval
|
|
20
|
+
* flip, participant dedup) — now the reducer's own state transitions via
|
|
21
|
+
* `./message-mutations`;
|
|
22
|
+
* - `useSseChatAdapter`/`useChat`'s SSE turn kernel (cumulative text
|
|
23
|
+
* replace, front-inserted thinking, approval card, `decision_resolved`
|
|
24
|
+
* receipt + cardRef stamping, sendIdx-keyed sources/refs/meta maps).
|
|
25
|
+
*
|
|
26
|
+
* Idempotency:
|
|
27
|
+
* - events whose `seq` ≤ the last applied seq are dropped (per instance);
|
|
28
|
+
* - participant rows additionally dedup via a one-shot optimistic-echo
|
|
29
|
+
* list and a short same-author content window (seq-less transports);
|
|
30
|
+
* - value-level no-op merges return prior references (see
|
|
31
|
+
* `message-mutations.ts`).
|
|
32
|
+
*
|
|
33
|
+
* TRANSPORT ORDERING ASSUMPTION (the seq gate, see `apply()`): every
|
|
34
|
+
* transport feeding this reducer is AT-LEAST-ONCE and IN-ORDER. JetStream
|
|
35
|
+
* redelivers (hence the gate) but never reorders within a stream, and the
|
|
36
|
+
* catchup back-fill replays a monotonically increasing range. So `seq <=
|
|
37
|
+
* lastAppliedSeq` means "already applied", and dropping is correct.
|
|
38
|
+
* A genuinely out-of-order arrival (seq 5 then 4) would be discarded
|
|
39
|
+
* PERMANENTLY — accepted deliberately: no transport here reorders, and an
|
|
40
|
+
* out-of-order buffer would add latency + unbounded state to guard against
|
|
41
|
+
* a case that cannot occur. If a reordering transport is ever added, this
|
|
42
|
+
* gate is the place that must change (do not paper over it downstream).
|
|
43
|
+
*
|
|
44
|
+
* `resolvePendingApprovalForExecution` (the accumulator's implicit
|
|
45
|
+
* approve-on-execution) is reachable ONLY on `transport: 'nats'` — the SSE
|
|
46
|
+
* kernel never routes tool executions through the accumulator.
|
|
47
|
+
*
|
|
48
|
+
* PURE + framework-free: no React, no timers, no network. Side effects the
|
|
49
|
+
* UI needs (approve/reject POSTs) enter as opaque callbacks stamped onto
|
|
50
|
+
* approval segments.
|
|
51
|
+
*/
|
|
52
|
+
import { type AccumulatorCallbacks } from '../utils/message-segment-accumulator';
|
|
53
|
+
import { type ScrollAnchor } from '../utils/scroll-anchor';
|
|
54
|
+
import type { ChatApprovalStatus, MessageSegment, PendingToolCallData, ToolExecutionSegment, ExecutingToolState } from '../types';
|
|
55
|
+
import type { PendingApproval } from '../types/processing.types';
|
|
56
|
+
import type { DialogTokenUsage, StreamingPhase, UnifiedChatMessage, UnifiedUsageBreakdown } from '../types/unified-chat-state.types';
|
|
57
|
+
import { type ChatStreamEvent } from '../../../chat-protocol/events';
|
|
58
|
+
import type { ChatRef } from '../chat-ref.types';
|
|
59
|
+
/** Per-turn metadata extracted from the streamed metadata/usage frames
|
|
60
|
+
* (SSE transport). Canonical home — `use-sse-chat-adapter` re-exports it. */
|
|
61
|
+
export interface ChatTurnMeta {
|
|
62
|
+
provider: string | null;
|
|
63
|
+
modelLabel: string | null;
|
|
64
|
+
contextWindowMaxTokens: number | null;
|
|
65
|
+
/** Input tokens (from usage:start). Includes cached tokens. */
|
|
66
|
+
inputTokens: number | null;
|
|
67
|
+
/** Output tokens (from the trailing usage frame). */
|
|
68
|
+
outputTokens: number | null;
|
|
69
|
+
/** Cache hit % (read / total-input × 100). Only known after stream end. */
|
|
70
|
+
cacheHitRatePct: number | null;
|
|
71
|
+
/** Cross-call usage breakdown extracted from the trailing usage frame. */
|
|
72
|
+
breakdown: UnifiedUsageBreakdown | null;
|
|
73
|
+
/** Per-message viewport-positioning hint. */
|
|
74
|
+
scrollAnchor: ScrollAnchor | null;
|
|
75
|
+
routedComplexity: string | null;
|
|
76
|
+
routedThinkingBudget: number | null;
|
|
77
|
+
}
|
|
78
|
+
/** Single source of truth for a fresh `ChatTurnMeta` row. */
|
|
79
|
+
export declare function createEmptyTurnMeta(): ChatTurnMeta;
|
|
80
|
+
/** SSE per-send maps, keyed by the send counter (`sendIdx`). Each user send
|
|
81
|
+
* produces ONE server-side refs/sources entry but can fan out to MULTIPLE
|
|
82
|
+
* assistant messages client-side — the adapter maps every following
|
|
83
|
+
* assistant message back to its send's entry. */
|
|
84
|
+
export interface ChatTurnMetaState {
|
|
85
|
+
meta: Map<number, ChatTurnMeta>;
|
|
86
|
+
sources: Map<number, unknown[]>;
|
|
87
|
+
refs: Map<number, Record<string, ChatRef>>;
|
|
88
|
+
sendCount: number;
|
|
89
|
+
}
|
|
90
|
+
export interface ChatReducerState {
|
|
91
|
+
messages: UnifiedChatMessage[];
|
|
92
|
+
streamingPhase: StreamingPhase;
|
|
93
|
+
turnMeta: ChatTurnMetaState;
|
|
94
|
+
dialogTokenUsage?: DialogTokenUsage | null;
|
|
95
|
+
liveModel?: {
|
|
96
|
+
provider: string | null;
|
|
97
|
+
modelLabel: string | null;
|
|
98
|
+
contextWindowMaxTokens: number | null;
|
|
99
|
+
} | null;
|
|
100
|
+
approvalStatuses: Record<string, ChatApprovalStatus>;
|
|
101
|
+
}
|
|
102
|
+
/** Escalated-approval bookkeeping entry (mirrors the legacy processor). */
|
|
103
|
+
export interface EscalatedApprovalData {
|
|
104
|
+
command: string;
|
|
105
|
+
explanation?: string;
|
|
106
|
+
approvalType: string;
|
|
107
|
+
toolCalls?: PendingToolCallData[];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Callback-visible effect produced by `apply()`. Names + args mirror the
|
|
111
|
+
* legacy `RealtimeChunkCallbacks` contract 1:1 — the contract the deleted
|
|
112
|
+
* `useRealtimeChunkProcessor` wrapper exposed, now pinned directly by
|
|
113
|
+
* `__tests__/chat-stream-reducer-golden.test.ts`.
|
|
114
|
+
*
|
|
115
|
+
* `segments-after-approval-result` is the one conditional emission: the
|
|
116
|
+
* legacy processor emitted a cumulative `onSegmentsUpdate` for a
|
|
117
|
+
* non-escalated APPROVAL_RESULT only when the consumer had NOT wired
|
|
118
|
+
* `onApprovalResolved` — the effect sink resolves that at dispatch time.
|
|
119
|
+
*/
|
|
120
|
+
export interface ChatReducerEffect {
|
|
121
|
+
name: 'onStreamStart' | 'onStreamEnd' | 'onMetadata' | 'onSegmentsUpdate' | 'onError' | 'onUserMessage' | 'onTokenUsage' | 'onDirectMessage' | 'onSystemMessage' | 'onEscalatedApproval' | 'onEscalatedApprovalResult' | 'onApprovalResolved' | 'onToolExecuted' | 'onAgentBusy' | 'onDialogClosed' | 'segments-after-approval-result';
|
|
122
|
+
args: unknown[];
|
|
123
|
+
}
|
|
124
|
+
export interface ChatStreamReducerOptions {
|
|
125
|
+
/** Which transport's turn kernel drives `apply()`. Default `'nats'`. */
|
|
126
|
+
transport?: 'sse' | 'nats';
|
|
127
|
+
/** Seed for the approval-status map (request-id → status). */
|
|
128
|
+
approvalStatuses?: Record<string, ChatApprovalStatus>;
|
|
129
|
+
/** Batch APPROVAL_REQUESTs render as one card (default true) or unfold. */
|
|
130
|
+
batchApprovalsEnabled?: boolean;
|
|
131
|
+
/** Approval types displayed inline; others escalate. Default ['CLIENT']. */
|
|
132
|
+
displayApprovalTypes?: string[];
|
|
133
|
+
/** Opaque approve/reject handlers stamped onto approval segments. */
|
|
134
|
+
callbacks?: AccumulatorCallbacks;
|
|
135
|
+
/** Engage the direct-mode barrier optimistically (host-known takeover). */
|
|
136
|
+
isDirectMode?: boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Legacy-processor parity knob: post-MESSAGE_END tool chunks route
|
|
139
|
+
* cross-message (`onToolExecuted` effect + `applyToolExecutionToMessages`)
|
|
140
|
+
* only when the consumer wired the cross-message updater; otherwise they
|
|
141
|
+
* fall through the accumulator like the pre-callback code path. Default
|
|
142
|
+
* true (both first-party adapters wire it).
|
|
143
|
+
*/
|
|
144
|
+
crossMessageToolRouting?: boolean;
|
|
145
|
+
/** Effect sink for callback-contract consumers (compat wrapper). */
|
|
146
|
+
onEffect?: (effect: ChatReducerEffect) => void;
|
|
147
|
+
/** Notified after every state mutation (the dialog store wires this). */
|
|
148
|
+
onChange?: () => void;
|
|
149
|
+
/**
|
|
150
|
+
* Whether an ADMIN-authored `MESSAGE_REQUEST` may be consumed as OUR OWN
|
|
151
|
+
* optimistic echo (see `pushOptimisticSend`). Default `false`.
|
|
152
|
+
*
|
|
153
|
+
* Who the local operator is decides this, and it differs per host:
|
|
154
|
+
* - Hub website chat / ticket CLIENT side: the local user is NEVER the
|
|
155
|
+
* admin, so an ADMIN-authored inbound row is a technician's reply and
|
|
156
|
+
* must ALWAYS render. Consuming it as an echo would silently delete a
|
|
157
|
+
* real message whenever its text happened to match ours. → `false`.
|
|
158
|
+
* - OpenFrame product app (Mingo + ticket ADMIN side): the operator IS
|
|
159
|
+
* the admin, so their own sends echo back as ADMIN and MUST be
|
|
160
|
+
* deduped, or every message renders twice. → `true`.
|
|
161
|
+
*
|
|
162
|
+
* Only ever applies to text the host itself registered via
|
|
163
|
+
* `pushOptimisticSend`, so enabling it cannot drop a message the host
|
|
164
|
+
* did not just send.
|
|
165
|
+
*/
|
|
166
|
+
ownEchoIncludesAdmin?: boolean;
|
|
167
|
+
/**
|
|
168
|
+
* The LOCAL user's id, either as a value or as a GETTER resolved at event
|
|
169
|
+
* time. When it resolves to a value, an inbound `MESSAGE_REQUEST` that
|
|
170
|
+
* DECLARES a different author (`event.userId !== selfUserId`) may not be
|
|
171
|
+
* consumed as our own optimistic echo.
|
|
172
|
+
*
|
|
173
|
+
* Without it the echo list matches on RAW TEXT alone, which on a shared
|
|
174
|
+
* ADMIN side (two technicians in one ticket, `ownEchoIncludesAdmin: true`)
|
|
175
|
+
* can silently delete a colleague's message: if OUR send never echoes back,
|
|
176
|
+
* its entry stays armed and the next identical text from anyone — canned
|
|
177
|
+
* replies like "ok" / "done" / "on it" make this routine — is swallowed.
|
|
178
|
+
*
|
|
179
|
+
* The guard FAILS OPEN, deliberately: a row that carries NO `userId` is not
|
|
180
|
+
* "someone else's", it is UNATTRIBUTED, and rejecting it would disable
|
|
181
|
+
* dedup entirely (→ every send rendered twice) on any transport whose
|
|
182
|
+
* decoder does not surface the author id. Such a row falls back to the
|
|
183
|
+
* text + `OWN_ECHO_TTL_MS` behaviour instead, and a one-shot `console.warn`
|
|
184
|
+
* makes the missing id observable.
|
|
185
|
+
*
|
|
186
|
+
* Pass a FUNCTION whenever the id can change or arrive late (auth
|
|
187
|
+
* rehydration, logout / login-as-another-user without a reload): reducers
|
|
188
|
+
* are retained for the store's lifetime, so a value captured at creation
|
|
189
|
+
* time can go stale and silently disable the guard.
|
|
190
|
+
*/
|
|
191
|
+
selfUserId?: string | (() => string | undefined);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* How long an un-consumed optimistic-echo entry stays armed **on the
|
|
195
|
+
* UNATTRIBUTED path**. Long enough to cover any realistic send → server-echo
|
|
196
|
+
* round trip, short enough that a send whose echo never lands cannot swallow
|
|
197
|
+
* an unrelated identical message later in the conversation.
|
|
198
|
+
*
|
|
199
|
+
* A row that is DECLARED ours (`selfUserId` set and `event.userId ===
|
|
200
|
+
* selfUserId`) gets the LONGER `OWN_ECHO_AUTHOR_TTL_MS` instead — see there.
|
|
201
|
+
*/
|
|
202
|
+
export declare const OWN_ECHO_TTL_MS = 30000;
|
|
203
|
+
/**
|
|
204
|
+
* How long an un-consumed entry stays armed on the AUTHOR-MATCHED path
|
|
205
|
+
* (`selfUserId` set, inbound row declares the same author).
|
|
206
|
+
*
|
|
207
|
+
* The author check rules out CROSS-technician theft, but NOT the same user on
|
|
208
|
+
* a second tab or device: a row THIS tab did not originate looks exactly like
|
|
209
|
+
* an author-matched echo. So the entry still needs an upper bound — without
|
|
210
|
+
* one, a send whose echo never lands (dropped frame, backend text
|
|
211
|
+
* normalization, reconnect gap) leaves the entry armed for the reducer's
|
|
212
|
+
* whole lifetime, and the next identical text from the same user on ANOTHER
|
|
213
|
+
* tab is silently swallowed. With `MAX_PENDING_ECHOES` armed slots and canned
|
|
214
|
+
* replies ("ok", "done", "on it") being exactly the recurring strings, that is
|
|
215
|
+
* a routine message-LOSS bug, strictly worse than the duplicate row it trades
|
|
216
|
+
* against.
|
|
217
|
+
*
|
|
218
|
+
* Ten minutes is the bound: generously longer than the slow echo the author
|
|
219
|
+
* path exists to protect (a JetStream catch-up replay after a network gap
|
|
220
|
+
* arrives long after the send, and its rows carry `seq`, so the seq-less
|
|
221
|
+
* content-dedup fallback cannot rescue it), and far shorter than the
|
|
222
|
+
* "same text again an hour later" window in which a stale entry does damage.
|
|
223
|
+
*
|
|
224
|
+
* It is a BACKSTOP, not the usual bound: `turn-end` disarms entries much
|
|
225
|
+
* sooner (see `purgeEchoesAtTurnEnd`). The ten minutes only ever apply to a
|
|
226
|
+
* dialog that never reports a turn boundary at all.
|
|
227
|
+
*/
|
|
228
|
+
export declare const OWN_ECHO_AUTHOR_TTL_MS: number;
|
|
229
|
+
/** One armed optimistic-echo entry: the sent text and the wall-clock ms it was
|
|
230
|
+
* armed at. Exported because the LRU-eviction round trip PARKS these (see
|
|
231
|
+
* `getPendingEchoes` / `InitializeExtras.pendingEchoes`). */
|
|
232
|
+
export interface PendingEcho {
|
|
233
|
+
text: string;
|
|
234
|
+
at: number;
|
|
235
|
+
}
|
|
236
|
+
export interface InitializeExtras {
|
|
237
|
+
existingSegments?: MessageSegment[];
|
|
238
|
+
pendingApprovals?: Map<string, PendingApproval>;
|
|
239
|
+
executingTools?: Map<string, ExecutingToolState>;
|
|
240
|
+
escalatedApprovals?: Map<string, EscalatedApprovalData>;
|
|
241
|
+
/**
|
|
242
|
+
* Approval statuses PARKED from a previous instance of this key (LRU
|
|
243
|
+
* eviction hands them to `onEvict`). Merged with the same state-monotonic
|
|
244
|
+
* precedence as `mergeApprovalStatuses` — a resolved approval must not come
|
|
245
|
+
* back as actionable, which is exactly why `resetForDialogSwitch` preserves
|
|
246
|
+
* this map rather than clearing it.
|
|
247
|
+
*/
|
|
248
|
+
approvalStatuses?: Record<string, ChatApprovalStatus>;
|
|
249
|
+
/**
|
|
250
|
+
* Seq cursor PARKED from a previous instance of this key. A recreated
|
|
251
|
+
* reducer starts at `-Infinity`, so a host that replays from its own cursor
|
|
252
|
+
* would re-apply already-applied events; restoring the parked value keeps
|
|
253
|
+
* `apply()`'s idempotency gate intact across an eviction. Only ever moves
|
|
254
|
+
* the gate FORWARD (a lower value is ignored).
|
|
255
|
+
*/
|
|
256
|
+
lastAppliedSeq?: number;
|
|
257
|
+
/**
|
|
258
|
+
* Armed optimistic-echo entries PARKED from a previous instance of this key.
|
|
259
|
+
* Without them, a key LRU-evicted between `pushOptimisticSend` and its
|
|
260
|
+
* `MESSAGE_REQUEST` echo leaves the replacement reducer with nothing armed,
|
|
261
|
+
* so the echo renders a DUPLICATE user bubble. Entries already past
|
|
262
|
+
* `OWN_ECHO_AUTHOR_TTL_MS` are dropped on restore (an expired entry could
|
|
263
|
+
* only swallow an unrelated identical message), and the list is capped at
|
|
264
|
+
* `MAX_PENDING_ECHOES` exactly as the live path is.
|
|
265
|
+
*/
|
|
266
|
+
pendingEchoes?: readonly PendingEcho[];
|
|
267
|
+
/**
|
|
268
|
+
* Whether the restored thread is a RESUMED dialog (a `MESSAGE_START` already
|
|
269
|
+
* fired server-side), which makes post-stream continuation chunks append
|
|
270
|
+
* into the existing bubble instead of taking the cold-start cumulative path.
|
|
271
|
+
* Defaults to "the restored thread is non-empty" — an eviction restore of a
|
|
272
|
+
* key that never streamed must NOT claim it did, or a cold text-delta with
|
|
273
|
+
* no preceding `turn-start` appends into a bubble that was never spawned.
|
|
274
|
+
* Pass explicitly only to override that derivation.
|
|
275
|
+
*/
|
|
276
|
+
resumed?: boolean;
|
|
277
|
+
/**
|
|
278
|
+
* Whether the restored tail means the AGENT IS STILL WORKING — as opposed to
|
|
279
|
+
* blocked on the user. Raises an `idle` reducer to `thinking` on restore
|
|
280
|
+
* (same rule as a live `onAgentBusy`: an open stream keeps the phase), which
|
|
281
|
+
* is what puts the activity indicator back.
|
|
282
|
+
*
|
|
283
|
+
* Nothing on the wire restores this: the phase machine is driven by events,
|
|
284
|
+
* and a run's EXECUTING chunk is long past by the time a reload happens while
|
|
285
|
+
* its EXECUTED one may be minutes away. Derived once by
|
|
286
|
+
* `extractIncompleteMessageState` so every host agrees on the distinction —
|
|
287
|
+
* a PENDING approval is the opposite state and must NOT spin.
|
|
288
|
+
*/
|
|
289
|
+
agentBusy?: boolean;
|
|
290
|
+
}
|
|
291
|
+
export interface BeginSseSendOptions {
|
|
292
|
+
text: string;
|
|
293
|
+
hidden?: boolean;
|
|
294
|
+
userName?: string;
|
|
295
|
+
assistantName?: string;
|
|
296
|
+
assistantAvatar?: string;
|
|
297
|
+
}
|
|
298
|
+
export interface ChatStreamReducer {
|
|
299
|
+
/** Apply one normalized stream event. */
|
|
300
|
+
apply(event: ChatStreamEvent): void;
|
|
301
|
+
/** Current immutable state snapshot (stable identity between mutations). */
|
|
302
|
+
readonly state: ChatReducerState;
|
|
303
|
+
/** Full reset — thread, per-turn kernel, dedup sets, seq gate, maps. */
|
|
304
|
+
reset(): void;
|
|
305
|
+
/**
|
|
306
|
+
* Seed the thread (history hydration / persisted-state rehydration) and
|
|
307
|
+
* optionally the per-turn kernel + escalated approvals (resume of an
|
|
308
|
+
* incomplete turn). `messages: null` keeps the current thread. Escalated
|
|
309
|
+
* entries are re-surfaced via `onEscalatedApproval` effects. Marks the
|
|
310
|
+
* instance as having streamed so continuation chunks append.
|
|
311
|
+
*/
|
|
312
|
+
initializeWithState(messages: UnifiedChatMessage[] | null, extras?: InitializeExtras): void;
|
|
313
|
+
setMessages(messages: UnifiedChatMessage[]): void;
|
|
314
|
+
prependMessages(messages: UnifiedChatMessage[]): void;
|
|
315
|
+
/** Optimistic local send: user bubble (+ echo record) + assistant placeholder. */
|
|
316
|
+
pushOptimisticSend(text: string, hidden?: boolean): void;
|
|
317
|
+
/** Wipe thread + per-turn kernel, keep approval statuses (legacy clear). */
|
|
318
|
+
clearThread(): void;
|
|
319
|
+
/** Per-dialog reset (keeps approval statuses — request-ids are global). */
|
|
320
|
+
resetForDialogSwitch(): void;
|
|
321
|
+
beginSseSend(options: BeginSseSendOptions): void;
|
|
322
|
+
endSseTurn(): void;
|
|
323
|
+
failSseTurn(errorMessage: string): void;
|
|
324
|
+
seedSseMaps(seed: {
|
|
325
|
+
sources?: Array<[number, unknown[]]>;
|
|
326
|
+
refs?: Array<[number, Record<string, ChatRef>]>;
|
|
327
|
+
sendCount?: number;
|
|
328
|
+
}): void;
|
|
329
|
+
setPhase(phase: StreamingPhase): void;
|
|
330
|
+
setApprovalStatus(requestId: string, status: ChatApprovalStatus | null): void;
|
|
331
|
+
/**
|
|
332
|
+
* CANONICAL merge of a PERSISTED status map (host-side store, history
|
|
333
|
+
* hydration, dialog-switch top-up) into this reducer's map.
|
|
334
|
+
*
|
|
335
|
+
* Precedence is STATE-MONOTONIC, not source-based, because either side can
|
|
336
|
+
* be the stale one:
|
|
337
|
+
* - persisted lags (a snapshot taken before the stream resolved the
|
|
338
|
+
* request) → the stream's resolved status must win, or a just-approved
|
|
339
|
+
* card would be downgraded back to `pending` and re-arm its buttons;
|
|
340
|
+
* - the STREAM lags (this tab saw the request, the operator resolved it in
|
|
341
|
+
* a SECOND TAB, and the persisted map is the one carrying the truth) →
|
|
342
|
+
* the persisted resolution must win, or the card stays actionable and
|
|
343
|
+
* invites a second approve on an already-resolved request.
|
|
344
|
+
*
|
|
345
|
+
* With statuses being exactly `pending | approved | rejected | cancelled`,
|
|
346
|
+
* "resolved beats pending" is a total order that gets both directions
|
|
347
|
+
* right: take the persisted value when ours is `pending` and theirs isn't;
|
|
348
|
+
* keep ours otherwise. Persisted entries still fill in every request-id the
|
|
349
|
+
* stream hasn't seen (other dialogs, pre-session history).
|
|
350
|
+
*/
|
|
351
|
+
mergeApprovalStatuses(persisted: Record<string, ChatApprovalStatus>): void;
|
|
352
|
+
setDirectMode(isDirectMode: boolean): void;
|
|
353
|
+
setDialogTokenUsage(usage: DialogTokenUsage | null): void;
|
|
354
|
+
/** +1/-1 windows during catchup replay (suppresses agent-busy locks). */
|
|
355
|
+
adjustAgentBusySuppression(delta: number): void;
|
|
356
|
+
armAdoptTrailingAssistant(value: boolean): void;
|
|
357
|
+
projectApprovalResolution(requestId: string, status: ChatApprovalStatus, resolvedByName?: string | null): void;
|
|
358
|
+
projectToolExecution(segment: ToolExecutionSegment): void;
|
|
359
|
+
/**
|
|
360
|
+
* The seq gate's current value (`-Infinity` before anything seq-carrying was
|
|
361
|
+
* applied). Not part of `state` — it is bookkeeping, not render input — but
|
|
362
|
+
* a host that PARKS a reducer (LRU eviction, dialog swap) needs it to
|
|
363
|
+
* restore idempotency on the recreated instance via
|
|
364
|
+
* `initializeWithState(messages, { lastAppliedSeq })`.
|
|
365
|
+
*/
|
|
366
|
+
getLastAppliedSeq(): number;
|
|
367
|
+
/**
|
|
368
|
+
* Currently-armed optimistic-echo entries. Same rationale as
|
|
369
|
+
* `getLastAppliedSeq`: not render input, but a host that PARKS a reducer
|
|
370
|
+
* needs them to restore echo dedup on the recreated instance via
|
|
371
|
+
* `initializeWithState(messages, { pendingEchoes })` — otherwise an echo
|
|
372
|
+
* in flight across the eviction renders a duplicate user bubble.
|
|
373
|
+
*/
|
|
374
|
+
getPendingEchoes(): readonly PendingEcho[];
|
|
375
|
+
getSegments(): MessageSegment[];
|
|
376
|
+
updateApprovalStatus(requestId: string, status: ChatApprovalStatus, resolvedByName?: string | null): MessageSegment[];
|
|
377
|
+
getPendingEscalated(): Map<string, EscalatedApprovalData>;
|
|
378
|
+
}
|
|
379
|
+
export declare function createChatStreamReducer(options?: ChatStreamReducerOptions): ChatStreamReducer;
|
|
380
|
+
//# sourceMappingURL=chat-stream-reducer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-stream-reducer.d.ts","sourceRoot":"","sources":["../../../../src/components/chat/stream/chat-stream-reducer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createDeltaBatcher — framework-free, append-only batching of the
|
|
3
|
+
* `text-delta` / `thinking-delta` / `guide-delta` events.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS IS SHARED (and not a hook-private detail): every host that drives a
|
|
6
|
+
* `ChatStreamReducer` from a raw transport needs the SAME batching, and a
|
|
7
|
+
* copy-paste of it drifts. The React wrapper (`useChatStreamReducer`) and any
|
|
8
|
+
* non-React mirror in a product app both consume this one implementation.
|
|
9
|
+
*
|
|
10
|
+
* Behaviour:
|
|
11
|
+
* - `push(event, key)` queues delta events and returns true; anything else
|
|
12
|
+
* returns false so the caller can flush + apply it synchronously (ordering:
|
|
13
|
+
* completion state must always land on fully-applied deltas).
|
|
14
|
+
* - CONSECUTIVE same-type deltas are COALESCED into one event (the reducer's
|
|
15
|
+
* append semantics distribute over concatenation), so a 60-delta/sec turn
|
|
16
|
+
* costs ONE `applyOne` per frame instead of 60. `text-delta` additionally
|
|
17
|
+
* requires a matching `leading` flag before coalescing.
|
|
18
|
+
* - A flush is scheduled on `requestAnimationFrame` when available, with a
|
|
19
|
+
* timer fallback that is ALWAYS armed (rAF pauses in background tabs, and a
|
|
20
|
+
* hidden chat panel must still keep its thread current).
|
|
21
|
+
* - `key` is an opaque routing token handed back to `applyOne`. When it
|
|
22
|
+
* changes, the pending batch is flushed against the PREVIOUS key first, so
|
|
23
|
+
* deltas never land on the wrong dialog/side.
|
|
24
|
+
*/
|
|
25
|
+
import type { ChatStreamEvent, GuideDeltaEvent, TextDeltaEvent, ThinkingDeltaEvent } from '../../../chat-protocol/events';
|
|
26
|
+
export declare const DELTA_FLUSH_FALLBACK_MS = 50;
|
|
27
|
+
export type DeltaEvent = TextDeltaEvent | ThinkingDeltaEvent | GuideDeltaEvent;
|
|
28
|
+
export declare function isDeltaEvent(event: ChatStreamEvent): event is DeltaEvent;
|
|
29
|
+
export interface CreateDeltaBatcherOptions<K> {
|
|
30
|
+
/** Apply one (possibly coalesced) delta against `key`'s reducer. */
|
|
31
|
+
applyOne: (event: DeltaEvent, key: K | undefined) => void;
|
|
32
|
+
/** Called after a flush that applied at least one delta. */
|
|
33
|
+
onFlushed?: (appliedCount: number) => void;
|
|
34
|
+
/** Timer fallback in ms (default `DELTA_FLUSH_FALLBACK_MS`). */
|
|
35
|
+
fallbackMs?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface DeltaBatcher<K = unknown> {
|
|
38
|
+
/**
|
|
39
|
+
* Queue `event` when it is a delta (returns true). Non-delta events are NOT
|
|
40
|
+
* queued and return false — the caller flushes and applies them itself.
|
|
41
|
+
*/
|
|
42
|
+
push(event: ChatStreamEvent, key?: K): boolean;
|
|
43
|
+
/** Synchronously apply the pending batch and cancel any scheduled flush. */
|
|
44
|
+
flush(): void;
|
|
45
|
+
/** Flush and release timers — call on teardown so tail deltas aren't lost. */
|
|
46
|
+
dispose(): void;
|
|
47
|
+
/** Queued (post-coalescing) delta count. Test/diagnostic surface. */
|
|
48
|
+
readonly pendingCount: number;
|
|
49
|
+
}
|
|
50
|
+
export declare function createDeltaBatcher<K = unknown>({ applyOne, onFlushed, fallbackMs, }: CreateDeltaBatcherOptions<K>): DeltaBatcher<K>;
|
|
51
|
+
//# sourceMappingURL=delta-batcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delta-batcher.d.ts","sourceRoot":"","sources":["../../../../src/components/chat/stream/delta-batcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,cAAc,EACd,kBAAkB,EACnB,MAAM,+BAA+B,CAAA;AAEtC,eAAO,MAAM,uBAAuB,KAAK,CAAA;AAEzC,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,kBAAkB,GAAG,eAAe,CAAA;AAE9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,KAAK,IAAI,UAAU,CAMxE;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,oEAAoE;IACpE,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,CAAA;IACzD,4DAA4D;IAC5D,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAA;IAC9C,4EAA4E;IAC5E,KAAK,IAAI,IAAI,CAAA;IACb,8EAA8E;IAC9E,OAAO,IAAI,IAAI,CAAA;IACf,qEAAqE;IACrE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC9B;AAED,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAAE,EAC9C,QAAQ,EACR,SAAS,EACT,UAAoC,GACrC,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAgGhD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat stream module — ONE master reader for every chat event source
|
|
3
|
+
* (SSE decoder, NATS chunk decoder, historical replay). See
|
|
4
|
+
* `chat-stream-reducer.ts` for the architecture note.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: the pure message-mutation helpers (`appendToTrailingAssistant`,
|
|
7
|
+
* `applyToolExecutionToMessages`, …) are intentionally NOT star-exported
|
|
8
|
+
* here — their legacy public home is `use-nats-chat-adapter`, which
|
|
9
|
+
* re-exports them from `./message-mutations`; exporting the same bindings
|
|
10
|
+
* from two star-exported barrels would make them ambiguous and drop them
|
|
11
|
+
* from the chat barrel entirely.
|
|
12
|
+
*/
|
|
13
|
+
export { createChatStreamReducer, createEmptyTurnMeta, type BeginSseSendOptions, type ChatReducerEffect, type ChatReducerState, type ChatStreamReducer, type ChatStreamReducerOptions, type ChatTurnMetaState, type EscalatedApprovalData, type InitializeExtras, type PendingEcho, } from './chat-stream-reducer';
|
|
14
|
+
export { createChatDialogStore, DEFAULT_DIALOG_SIDE, DEFAULT_MAX_REDUCERS, MAX_PENDING_RETAIN_KEYS, type ChatDialogSide, type ChatDialogStore, type CreateChatDialogStoreOptions, type EvictedReducerState, } from './chat-dialog-store';
|
|
15
|
+
export { createDeltaBatcher, type CreateDeltaBatcherOptions, type DeltaBatcher, type DeltaEvent, } from './delta-batcher';
|
|
16
|
+
export { useChatStreamReducer, type UseChatStreamReducerOptions, type UseChatStreamReducerReturn, } from './use-chat-stream-reducer';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/chat/stream/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,WAAW,GACjB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAA;AAO5B,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,YAAY,EACjB,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,GAChC,MAAM,2BAA2B,CAAA"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure message-mutation kernel for the master chat-stream reducer.
|
|
3
|
+
*
|
|
4
|
+
* These helpers were absorbed from `use-nats-chat-adapter.ts` in Phase 3 of
|
|
5
|
+
* the chat unification — they are the ONE implementation of "apply a stream
|
|
6
|
+
* fragment to a message thread". The reducer (`chat-stream-reducer.ts`) and
|
|
7
|
+
* the cross-side projections (`chat-dialog-store.ts`) both build on them.
|
|
8
|
+
*
|
|
9
|
+
* REFERENTIAL-STABILITY CONTRACT: every helper clones ONLY the touched
|
|
10
|
+
* message object (and the touched segment slot inside it). A value-level
|
|
11
|
+
* no-op — e.g. a replayed duplicate EXECUTED_TOOL whose merge would write
|
|
12
|
+
* identical values — returns the PRIOR references untouched, so React
|
|
13
|
+
* memoization over untouched messages survives redeliveries.
|
|
14
|
+
*
|
|
15
|
+
* Framework-free: no React, no timers.
|
|
16
|
+
*/
|
|
17
|
+
import type { ChatApprovalStatus, MessageSegment, ToolExecutionSegment } from '../types';
|
|
18
|
+
import type { UnifiedChatMessage } from '../types/unified-chat-state.types';
|
|
19
|
+
export declare function nextId(role: 'user' | 'assistant'): string;
|
|
20
|
+
/**
|
|
21
|
+
* Realtime user/direct/system chunks can be replays of rows already on
|
|
22
|
+
* screen. Content-window dedup is the LAST layer (seq-less transports only)
|
|
23
|
+
* — see the layer list in `chat-stream-reducer.ts`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const CONTENT_DEDUP_WINDOW = 4;
|
|
26
|
+
export declare const SYSTEM_DEDUP_WINDOW = 10;
|
|
27
|
+
export declare function hasRecentMessage(prev: UnifiedChatMessage[], predicate: (message: UnifiedChatMessage) => boolean, window: number): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Replace (or append) the trailing assistant message with the latest
|
|
30
|
+
* accumulated segments.
|
|
31
|
+
*/
|
|
32
|
+
export declare function updateTrailingAssistant(prev: UnifiedChatMessage[], segments: MessageSegment[]): UnifiedChatMessage[];
|
|
33
|
+
/**
|
|
34
|
+
* Append-mode counterpart of `updateTrailingAssistant` for post-MESSAGE_END
|
|
35
|
+
* continuation fragments (`SegmentsUpdateMetadata.append`). Coalesces
|
|
36
|
+
* trailing fragments of the same type, mirroring the accumulator; approval
|
|
37
|
+
* deltas upsert by request id so a replayed emit stays idempotent.
|
|
38
|
+
*/
|
|
39
|
+
export declare function appendToTrailingAssistant(prev: UnifiedChatMessage[], segments: MessageSegment[]): UnifiedChatMessage[];
|
|
40
|
+
/**
|
|
41
|
+
* Upsert a standalone context-compaction segment into the trailing assistant
|
|
42
|
+
* bubble. Compaction emissions arrive as the accumulator's CUMULATIVE array —
|
|
43
|
+
* only the compaction segment itself may be applied, or interleaved
|
|
44
|
+
* continuation text would duplicate. A `completed` segment replaces the last
|
|
45
|
+
* `started` one in place.
|
|
46
|
+
*/
|
|
47
|
+
export declare function upsertTrailingCompaction(prev: UnifiedChatMessage[], segments: MessageSegment[]): UnifiedChatMessage[];
|
|
48
|
+
/**
|
|
49
|
+
* Cross-message tool-execution updater for post-MESSAGE_END tool chunks
|
|
50
|
+
* (approved commands executing after the approval bubble, async batch
|
|
51
|
+
* results). Scans messages from the end:
|
|
52
|
+
* 1) an `approval_batch` whose `toolCalls` contains the execution id →
|
|
53
|
+
* merge into its `executions` map;
|
|
54
|
+
* 2) a matching `tool_execution` segment (same id, or EXECUTING with the
|
|
55
|
+
* same tool for legacy id-less backends) → update in place;
|
|
56
|
+
* 3) no match → append the segment to the trailing assistant bubble.
|
|
57
|
+
*
|
|
58
|
+
* A value-level no-op (replayed duplicate) returns `prev` untouched.
|
|
59
|
+
*/
|
|
60
|
+
export declare function applyToolExecutionToMessages(prev: UnifiedChatMessage[], segment: ToolExecutionSegment): UnifiedChatMessage[];
|
|
61
|
+
/**
|
|
62
|
+
* Merge-only variant of `applyToolExecutionToMessages` — the pure projection
|
|
63
|
+
* used for the cross-SIDE fan-out in `chat-dialog-store.ts`. Updates a
|
|
64
|
+
* matching batch slot / tool segment when present; returns `null` when
|
|
65
|
+
* nothing matches (the caller decides whether to append — projections never
|
|
66
|
+
* do, so a tool that belongs to one side only never grows a card on the
|
|
67
|
+
* other).
|
|
68
|
+
*/
|
|
69
|
+
export declare function mergeToolExecutionIfPresent(prev: UnifiedChatMessage[], segment: ToolExecutionSegment): UnifiedChatMessage[] | null;
|
|
70
|
+
/**
|
|
71
|
+
* Cross-message approval status flip (absorbed from the NATS adapter's
|
|
72
|
+
* `onApprovalResolved` handler). Idempotent + reference-preserving: only the
|
|
73
|
+
* messages/segments whose status (or resolvedByName) actually changes are
|
|
74
|
+
* cloned; a no-op returns `prev`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function projectApprovalResolutionToMessages(prev: UnifiedChatMessage[], requestId: string, status: ChatApprovalStatus, resolvedByName?: string | null): UnifiedChatMessage[];
|
|
77
|
+
//# sourceMappingURL=message-mutations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-mutations.d.ts","sourceRoot":"","sources":["../../../../src/components/chat/stream/message-mutations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAEV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EAErB,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAE3E,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAKzD;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAA;AACrC,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,kBAAkB,EAAE,EAC1B,SAAS,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,EACnD,MAAM,EAAE,MAAM,GACb,OAAO,CAMT;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,kBAAkB,EAAE,EAC1B,QAAQ,EAAE,cAAc,EAAE,GACzB,kBAAkB,EAAE,CAetB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,kBAAkB,EAAE,EAC1B,QAAQ,EAAE,cAAc,EAAE,GACzB,kBAAkB,EAAE,CAgDtB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,kBAAkB,EAAE,EAC1B,QAAQ,EAAE,cAAc,EAAE,GACzB,kBAAkB,EAAE,CAsBtB;AA2BD;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,kBAAkB,EAAE,EAC1B,OAAO,EAAE,oBAAoB,GAC5B,kBAAkB,EAAE,CAItB;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,kBAAkB,EAAE,EAC1B,OAAO,EAAE,oBAAoB,GAC5B,kBAAkB,EAAE,GAAG,IAAI,CA4E7B;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,kBAAkB,EAAE,EAC1B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,kBAAkB,EAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAC7B,kBAAkB,EAAE,CAuBtB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ChatStreamEvent } from '../../../chat-protocol/events';
|
|
2
|
+
import { type ChatDialogSide, type ChatDialogStore } from './chat-dialog-store';
|
|
3
|
+
import type { ChatReducerState, ChatStreamReducer, ChatStreamReducerOptions } from './chat-stream-reducer';
|
|
4
|
+
export interface UseChatStreamReducerOptions {
|
|
5
|
+
store: ChatDialogStore;
|
|
6
|
+
dialogId: string;
|
|
7
|
+
side?: ChatDialogSide;
|
|
8
|
+
/** Consulted once, when this (dialogId, side) reducer is first created. */
|
|
9
|
+
createReducerOptions?: () => ChatStreamReducerOptions;
|
|
10
|
+
}
|
|
11
|
+
export interface UseChatStreamReducerReturn {
|
|
12
|
+
state: ChatReducerState;
|
|
13
|
+
/** Apply a decoded event (deltas are batched; everything else immediate). */
|
|
14
|
+
applyEvent: (event: ChatStreamEvent) => void;
|
|
15
|
+
/** Synchronously apply any pending delta batch. */
|
|
16
|
+
flushDeltas: () => void;
|
|
17
|
+
/** Run reducer commands (adapter-driven, non-wire mutations). */
|
|
18
|
+
mutate: <T>(fn: (reducer: ChatStreamReducer) => T) => T;
|
|
19
|
+
reducer: ChatStreamReducer;
|
|
20
|
+
}
|
|
21
|
+
export declare function useChatStreamReducer({ store, dialogId, side, createReducerOptions, }: UseChatStreamReducerOptions): UseChatStreamReducerReturn;
|
|
22
|
+
//# sourceMappingURL=use-chat-stream-reducer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-chat-stream-reducer.d.ts","sourceRoot":"","sources":["../../../../src/components/chat/stream/use-chat-stream-reducer.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,uBAAuB,CAAA;AAO9B,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,eAAe,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,2EAA2E;IAC3E,oBAAoB,CAAC,EAAE,MAAM,wBAAwB,CAAA;CACtD;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,gBAAgB,CAAA;IACvB,6EAA6E;IAC7E,UAAU,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAC5C,mDAAmD;IACnD,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,iEAAiE;IACjE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,CAAC,KAAK,CAAC,CAAA;IACvD,OAAO,EAAE,iBAAiB,CAAA;CAC3B;AAED,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,QAAQ,EACR,IAA0B,EAC1B,oBAAoB,GACrB,EAAE,2BAA2B,GAAG,0BAA0B,CAiE1D"}
|