@flamingo-stack/openframe-frontend-core 0.0.660 → 0.0.661-2297.6904.1
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/{chunk-RRGTBH3L.cjs → chunk-4EY5JSMK.cjs} +5 -5
- package/dist/{chunk-RRGTBH3L.cjs.map → chunk-4EY5JSMK.cjs.map} +1 -1
- package/dist/{chunk-VW7NXM2O.cjs → chunk-4JITKV2S.cjs} +45 -45
- package/dist/{chunk-VW7NXM2O.cjs.map → chunk-4JITKV2S.cjs.map} +1 -1
- package/dist/{chunk-H7ORPMRH.js → chunk-4NKKPGDN.js} +21 -19
- package/dist/{chunk-H7ORPMRH.js.map → chunk-4NKKPGDN.js.map} +1 -1
- package/dist/{chunk-2DLM3NXE.js → chunk-5LS7KNAU.js} +5 -5
- package/dist/{chunk-GDHV5W5C.cjs → chunk-6VY6PXAN.cjs} +33 -33
- package/dist/{chunk-GDHV5W5C.cjs.map → chunk-6VY6PXAN.cjs.map} +1 -1
- package/dist/{chunk-UIAXQJPV.cjs → chunk-7KNVRRI4.cjs} +22 -22
- package/dist/{chunk-UIAXQJPV.cjs.map → chunk-7KNVRRI4.cjs.map} +1 -1
- package/dist/{chunk-ITVLOEGF.cjs → chunk-D7QWYQBQ.cjs} +71 -71
- package/dist/{chunk-ITVLOEGF.cjs.map → chunk-D7QWYQBQ.cjs.map} +1 -1
- package/dist/{chunk-6KR74SOJ.js → chunk-EUT6SQW7.js} +3 -3
- package/dist/{chunk-VFGBRGFB.js → chunk-F5LMTKQD.js} +3 -3
- package/dist/{chunk-MW7LEMFG.js → chunk-FC6I2NWF.js} +2 -2
- package/dist/{chunk-WMIB6JSA.cjs → chunk-GLDXZK76.cjs} +4 -4
- package/dist/{chunk-WMIB6JSA.cjs.map → chunk-GLDXZK76.cjs.map} +1 -1
- package/dist/{chunk-LSVQNRX4.cjs → chunk-GXHZCGVJ.cjs} +21 -19
- package/dist/chunk-GXHZCGVJ.cjs.map +1 -0
- package/dist/{chunk-L4YJU3AG.cjs → chunk-H3DF7COI.cjs} +15 -15
- package/dist/{chunk-L4YJU3AG.cjs.map → chunk-H3DF7COI.cjs.map} +1 -1
- package/dist/{chunk-KP4K6I5O.js → chunk-IMDYBINC.js} +3 -3
- package/dist/{chunk-ZT3CZCDS.js → chunk-J5TAB64U.js} +2 -2
- package/dist/{chunk-WWEQT2WX.js → chunk-KCYGLC7Q.js} +5 -5
- package/dist/{chunk-E7C3F2SK.js → chunk-M23ZPKOK.js} +2 -2
- package/dist/{chunk-Z7NI2TQD.cjs → chunk-N4ORXOZK.cjs} +10 -10
- package/dist/{chunk-Z7NI2TQD.cjs.map → chunk-N4ORXOZK.cjs.map} +1 -1
- package/dist/{chunk-P2ROGTMF.js → chunk-PC5WWTDM.js} +3 -3
- package/dist/{chunk-T6LNAX4R.js → chunk-Q4XWYP5U.js} +4 -4
- package/dist/{chunk-NXAXZPEO.cjs → chunk-QARWK4LN.cjs} +10 -10
- package/dist/{chunk-NXAXZPEO.cjs.map → chunk-QARWK4LN.cjs.map} +1 -1
- package/dist/{chunk-6DVSTVUU.js → chunk-RFGXKRRL.js} +6 -6
- package/dist/{chunk-K4W3II7M.cjs → chunk-RPHRBZG6.cjs} +3 -3
- package/dist/{chunk-K4W3II7M.cjs.map → chunk-RPHRBZG6.cjs.map} +1 -1
- package/dist/{chunk-VVOI2OC3.js → chunk-TRR6XUEP.js} +2 -2
- package/dist/{chunk-MEFCA6VD.js → chunk-U4N65JUW.js} +3 -3
- package/dist/{chunk-QVZD2LLU.js → chunk-WDJT7NJ5.js} +5 -5
- package/dist/{chunk-VWGFJJD6.cjs → chunk-WGTKYVBK.cjs} +10 -10
- package/dist/{chunk-VWGFJJD6.cjs.map → chunk-WGTKYVBK.cjs.map} +1 -1
- package/dist/{chunk-EOGXNLZC.cjs → chunk-XOA32PN3.cjs} +22 -22
- package/dist/{chunk-EOGXNLZC.cjs.map → chunk-XOA32PN3.cjs.map} +1 -1
- package/dist/{chunk-VJMPYY5O.cjs → chunk-YNW3DQFY.cjs} +25 -25
- package/dist/{chunk-VJMPYY5O.cjs.map → chunk-YNW3DQFY.cjs.map} +1 -1
- package/dist/{chunk-APWQTZCR.js → chunk-Z572FXXM.js} +2 -2
- package/dist/{chunk-AOOORZI5.cjs → chunk-ZASHVL45.cjs} +3 -3
- package/dist/{chunk-AOOORZI5.cjs.map → chunk-ZASHVL45.cjs.map} +1 -1
- package/dist/{chunk-PUE4XMZK.cjs → chunk-ZIT4TC5R.cjs} +163 -163
- package/dist/{chunk-PUE4XMZK.cjs.map → chunk-ZIT4TC5R.cjs.map} +1 -1
- package/dist/components/case-studies/index.cjs +14 -14
- package/dist/components/case-studies/index.js +3 -3
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/chat/utils/history-merge.d.ts +6 -0
- package/dist/components/chat/utils/history-merge.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +4 -4
- package/dist/components/contact/index.js +3 -3
- package/dist/components/docs/index.cjs +7 -7
- package/dist/components/docs/index.js +6 -6
- package/dist/components/embeds/index.cjs +4 -4
- package/dist/components/embeds/index.js +3 -3
- package/dist/components/faq/index.cjs +4 -4
- package/dist/components/faq/index.js +3 -3
- package/dist/components/features/index.cjs +3 -3
- package/dist/components/features/index.js +2 -2
- package/dist/components/help-center-pages/index.cjs +23 -23
- package/dist/components/help-center-pages/index.js +14 -14
- package/dist/components/index.cjs +39 -39
- package/dist/components/index.js +13 -13
- package/dist/components/meeting-scheduler/index.cjs +24 -24
- package/dist/components/meeting-scheduler/index.js +2 -2
- package/dist/components/navigation/index.cjs +6 -6
- package/dist/components/navigation/index.js +5 -5
- package/dist/components/onboarding-guides/index.cjs +6 -6
- package/dist/components/onboarding-guides/index.js +5 -5
- package/dist/components/tickets/index.cjs +7 -7
- package/dist/components/tickets/index.js +6 -6
- package/dist/components/ui/index.cjs +3 -3
- package/dist/components/ui/index.js +2 -2
- package/dist/index.cjs +7 -7
- package/dist/index.js +6 -6
- package/package.json +1 -1
- package/src/components/chat/utils/__tests__/history-merge.test.ts +62 -0
- package/src/components/chat/utils/history-merge.ts +31 -17
- package/dist/chunk-LSVQNRX4.cjs.map +0 -1
- /package/dist/{chunk-2DLM3NXE.js.map → chunk-5LS7KNAU.js.map} +0 -0
- /package/dist/{chunk-6KR74SOJ.js.map → chunk-EUT6SQW7.js.map} +0 -0
- /package/dist/{chunk-VFGBRGFB.js.map → chunk-F5LMTKQD.js.map} +0 -0
- /package/dist/{chunk-MW7LEMFG.js.map → chunk-FC6I2NWF.js.map} +0 -0
- /package/dist/{chunk-KP4K6I5O.js.map → chunk-IMDYBINC.js.map} +0 -0
- /package/dist/{chunk-ZT3CZCDS.js.map → chunk-J5TAB64U.js.map} +0 -0
- /package/dist/{chunk-WWEQT2WX.js.map → chunk-KCYGLC7Q.js.map} +0 -0
- /package/dist/{chunk-E7C3F2SK.js.map → chunk-M23ZPKOK.js.map} +0 -0
- /package/dist/{chunk-P2ROGTMF.js.map → chunk-PC5WWTDM.js.map} +0 -0
- /package/dist/{chunk-T6LNAX4R.js.map → chunk-Q4XWYP5U.js.map} +0 -0
- /package/dist/{chunk-6DVSTVUU.js.map → chunk-RFGXKRRL.js.map} +0 -0
- /package/dist/{chunk-VVOI2OC3.js.map → chunk-TRR6XUEP.js.map} +0 -0
- /package/dist/{chunk-MEFCA6VD.js.map → chunk-U4N65JUW.js.map} +0 -0
- /package/dist/{chunk-QVZD2LLU.js.map → chunk-WDJT7NJ5.js.map} +0 -0
- /package/dist/{chunk-APWQTZCR.js.map → chunk-Z572FXXM.js.map} +0 -0
|
@@ -24,6 +24,12 @@ export interface MergeableChatMessage {
|
|
|
24
24
|
role: string;
|
|
25
25
|
content: MessageContent;
|
|
26
26
|
timestamp?: Date;
|
|
27
|
+
/** Who authored a `user`-role row: the host's own user (`'user'` / unset),
|
|
28
|
+
* a technician (`'admin'`) or the system (`'system'`). Every host renders
|
|
29
|
+
* technician and system lines under role `user`, so a user row's twin must
|
|
30
|
+
* match on this as well as on text - otherwise the end user's "?" is taken
|
|
31
|
+
* for the twin of the technician's "?" and dropped from the thread. */
|
|
32
|
+
authorType?: string;
|
|
27
33
|
/** Highest CONTENT chunk streamSeq that composed this message (text / tool /
|
|
28
34
|
* approval / error / compaction — never the non-persisted MESSAGE_END /
|
|
29
35
|
* TOKEN_USAGE control chunks). Hosts stamp it on realtime synthetics so the
|
|
@@ -154,10 +160,17 @@ function sharesRequestKey(keys: ReadonlySet<string>, others: ReadonlySet<string>
|
|
|
154
160
|
return false;
|
|
155
161
|
}
|
|
156
162
|
|
|
157
|
-
/** A user row's identity is its text; empty text is no
|
|
158
|
-
* persist with `content: ''`). `''` for any other row.
|
|
159
|
-
|
|
160
|
-
|
|
163
|
+
/** A user row's identity is its text under its author kind; empty text is no
|
|
164
|
+
* identity (system rows persist with `content: ''`). `''` for any other row.
|
|
165
|
+
* The kind is part of the key because technician (`authorType: 'admin'`) and
|
|
166
|
+
* system rows share role `user` with the host's own sends: without it a
|
|
167
|
+
* technician who typed the same text is the own bubble's "twin", and the own
|
|
168
|
+
* bubble is dropped while its row is not in the snapshot yet. An unset
|
|
169
|
+
* authorType is the own user (hosts stamp `'admin'` on their own sends where
|
|
170
|
+
* the operator IS the admin, so the rule stays symmetric per host). */
|
|
171
|
+
function userTwinKey(m: MergeableChatMessage): string {
|
|
172
|
+
if (m.role !== 'user' || typeof m.content !== 'string' || m.content === '') return '';
|
|
173
|
+
return `${m.authorType ?? 'user'}\u0000${m.content}`;
|
|
161
174
|
}
|
|
162
175
|
|
|
163
176
|
/** What a set of rows says about the turns they render, so another copy of one
|
|
@@ -182,8 +195,8 @@ function collectTwinSignals(rows: readonly MergeableChatMessage[]): TwinSignals
|
|
|
182
195
|
if (text !== '') signals.assistantTexts.set(text, (signals.assistantTexts.get(text) ?? 0) + 1);
|
|
183
196
|
continue;
|
|
184
197
|
}
|
|
185
|
-
const
|
|
186
|
-
if (
|
|
198
|
+
const key = userTwinKey(row);
|
|
199
|
+
if (key !== '') signals.userContents.set(key, (signals.userContents.get(key) ?? 0) + 1);
|
|
187
200
|
}
|
|
188
201
|
return signals;
|
|
189
202
|
}
|
|
@@ -198,9 +211,9 @@ type TwinVerdict = 'twin' | 'distinct' | 'unknown';
|
|
|
198
211
|
* request id, no answer text), so "no match" says nothing about it. */
|
|
199
212
|
function twinVerdict(signals: TwinSignals, m: MergeableChatMessage): TwinVerdict {
|
|
200
213
|
if (m.role !== 'assistant') {
|
|
201
|
-
const
|
|
202
|
-
if (
|
|
203
|
-
return signals.userContents.has(
|
|
214
|
+
const key = userTwinKey(m);
|
|
215
|
+
if (key === '') return 'unknown';
|
|
216
|
+
return signals.userContents.has(key) ? 'twin' : 'distinct';
|
|
204
217
|
}
|
|
205
218
|
const keys = turnRequestKeys(m.content);
|
|
206
219
|
if (keys.size > 0) return sharesRequestKey(keys, signals.requestKeys) ? 'twin' : 'distinct';
|
|
@@ -529,7 +542,7 @@ export function mergeHistoryWithRealtime<M extends MergeableChatMessage>(input:
|
|
|
529
542
|
// optimistic messages are minted on send, never by chunk replay, so
|
|
530
543
|
// their timestamps are trustworthy.
|
|
531
544
|
const canBeInSnapshot = (m.timestamp?.getTime() ?? 0) <= historyFetchedAt;
|
|
532
|
-
return !(canBeInSnapshot && windowSignals.userContents.has(m
|
|
545
|
+
return !(canBeInSnapshot && windowSignals.userContents.has(userTwinKey(m)));
|
|
533
546
|
}
|
|
534
547
|
// Freshness rule: a synthetic whose turn is represented in the snapshot
|
|
535
548
|
// (under its persisted Mongo id) must be dropped or the turn renders
|
|
@@ -560,10 +573,11 @@ export function mergeHistoryWithRealtime<M extends MergeableChatMessage>(input:
|
|
|
560
573
|
// already does for DIRECT/SYSTEM), which also stops the replay at the
|
|
561
574
|
// source via a correct `optStartSeq`.
|
|
562
575
|
if (m.role === 'user' && isUserRequestSyntheticId(m.id) && typeof m.content === 'string') {
|
|
563
|
-
const
|
|
564
|
-
seenUserSyntheticByContent.
|
|
576
|
+
const twinKey = userTwinKey(m);
|
|
577
|
+
const seen = (seenUserSyntheticByContent.get(twinKey) ?? 0) + 1;
|
|
578
|
+
seenUserSyntheticByContent.set(twinKey, seen);
|
|
565
579
|
// No persisted row for THIS occurrence slot → keep (nothing renders it).
|
|
566
|
-
if ((windowSignals.userContents.get(
|
|
580
|
+
if ((windowSignals.userContents.get(twinKey) ?? 0) < seen) return true;
|
|
567
581
|
// A same-text persisted twin exists for this slot. User rows carry no
|
|
568
582
|
// persisted seq, so that twin may be THIS message's OWN row (drop — it
|
|
569
583
|
// renders the message) OR an OLDER identical-text turn while this is a
|
|
@@ -582,7 +596,7 @@ export function mergeHistoryWithRealtime<M extends MergeableChatMessage>(input:
|
|
|
582
596
|
if (typeof m.streamSeq !== 'number' || historyMaxStreamSeq <= 0) return false;
|
|
583
597
|
if (historyMaxStreamSeq >= m.streamSeq) return false;
|
|
584
598
|
const lastPersisted = processedToUse[processedToUse.length - 1];
|
|
585
|
-
if (lastPersisted && lastPersisted
|
|
599
|
+
if (lastPersisted && userTwinKey(lastPersisted) === twinKey) return false;
|
|
586
600
|
return true;
|
|
587
601
|
}
|
|
588
602
|
// Per-message seq coverage for the remaining synthetics (assistant /
|
|
@@ -701,10 +715,10 @@ export function computeHistoryPrepend<M extends MergeableChatMessage>(
|
|
|
701
715
|
for (let i = newEnd - 1; i >= 0; i--) {
|
|
702
716
|
const pm = processedHistory[i];
|
|
703
717
|
if (pm.role === 'user') {
|
|
704
|
-
const
|
|
705
|
-
const left =
|
|
718
|
+
const key = userTwinKey(pm);
|
|
719
|
+
const left = key === '' ? 0 : (userTwinsLeft.get(key) ?? 0);
|
|
706
720
|
if (left === 0) continue;
|
|
707
|
-
userTwinsLeft.set(
|
|
721
|
+
userTwinsLeft.set(key, left - 1);
|
|
708
722
|
twinIndices.add(i);
|
|
709
723
|
} else if (pm.role === 'assistant') {
|
|
710
724
|
const keys = turnRequestKeys(pm.content);
|