@flamingo-stack/openframe-frontend-core 0.0.444 → 0.0.445
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-DTMJWBDQ.js → chunk-22NSWMI6.js} +3 -3
- package/dist/{chunk-NDWIFCLS.js → chunk-3BHV2QAH.js} +555 -135
- package/dist/{chunk-NDWIFCLS.js.map → chunk-3BHV2QAH.js.map} +1 -1
- package/dist/{chunk-PMTR5W5G.js → chunk-3DQ5BFPM.js} +5 -5
- package/dist/{chunk-RALJEQWM.cjs → chunk-3HYSD7NR.cjs} +15 -15
- package/dist/{chunk-RALJEQWM.cjs.map → chunk-3HYSD7NR.cjs.map} +1 -1
- package/dist/{chunk-YP7VJPCJ.cjs → chunk-5DWPXK37.cjs} +40 -40
- package/dist/{chunk-YP7VJPCJ.cjs.map → chunk-5DWPXK37.cjs.map} +1 -1
- package/dist/{chunk-OXZLBIR7.cjs → chunk-5FUQTSTT.cjs} +18 -18
- package/dist/{chunk-OXZLBIR7.cjs.map → chunk-5FUQTSTT.cjs.map} +1 -1
- package/dist/{chunk-MG4AMIFX.js → chunk-5NYXGWBN.js} +2 -2
- package/dist/{chunk-LCJGOV6P.js → chunk-7R256DKK.js} +2 -2
- package/dist/{chunk-2PLNDTRG.cjs → chunk-DTLNCOSG.cjs} +32 -32
- package/dist/{chunk-2PLNDTRG.cjs.map → chunk-DTLNCOSG.cjs.map} +1 -1
- package/dist/{chunk-3SCNEGL2.js → chunk-FIAXFNAA.js} +5 -5
- package/dist/{chunk-FQASXKBK.js → chunk-G2KXNMFQ.js} +2 -2
- package/dist/{chunk-H7H3AFLF.js → chunk-H2DYCT6M.js} +2 -2
- package/dist/{chunk-CE3AITV2.js → chunk-H352AZJN.js} +6 -6
- package/dist/{chunk-DCDB3SM4.js → chunk-K4RASNQM.js} +3 -3
- package/dist/{chunk-WXU6A6CA.cjs → chunk-KISQUH33.cjs} +73 -73
- package/dist/{chunk-WXU6A6CA.cjs.map → chunk-KISQUH33.cjs.map} +1 -1
- package/dist/{chunk-BYTJNRJW.cjs → chunk-MPSA6YAM.cjs} +40 -40
- package/dist/{chunk-BYTJNRJW.cjs.map → chunk-MPSA6YAM.cjs.map} +1 -1
- package/dist/{chunk-ABIRMYG5.js → chunk-MQUS6BFR.js} +6 -6
- package/dist/{chunk-DSW6FIEF.cjs → chunk-N64VTHZ5.cjs} +7 -7
- package/dist/{chunk-DSW6FIEF.cjs.map → chunk-N64VTHZ5.cjs.map} +1 -1
- package/dist/{chunk-F6NMMPDL.cjs → chunk-P3FN4NAE.cjs} +29 -29
- package/dist/{chunk-F6NMMPDL.cjs.map → chunk-P3FN4NAE.cjs.map} +1 -1
- package/dist/{chunk-PHWQLKVE.js → chunk-P47NN7RY.js} +29 -31
- package/dist/chunk-P47NN7RY.js.map +1 -0
- package/dist/{chunk-2CJ734N2.cjs → chunk-PTT4J5GF.cjs} +3 -3
- package/dist/{chunk-2CJ734N2.cjs.map → chunk-PTT4J5GF.cjs.map} +1 -1
- package/dist/{chunk-4R3SVOKH.cjs → chunk-QL2EI56X.cjs} +797 -377
- package/dist/chunk-QL2EI56X.cjs.map +1 -0
- package/dist/{chunk-VI2QQIGR.cjs → chunk-R6WGCJBB.cjs} +73 -73
- package/dist/{chunk-VI2QQIGR.cjs.map → chunk-R6WGCJBB.cjs.map} +1 -1
- package/dist/{chunk-Q6XOEVPH.cjs → chunk-RXLMN6B5.cjs} +12 -12
- package/dist/{chunk-Q6XOEVPH.cjs.map → chunk-RXLMN6B5.cjs.map} +1 -1
- package/dist/{chunk-F2XHBAHT.js → chunk-TCEBFMLQ.js} +2 -2
- package/dist/{chunk-7CZ4MJSI.cjs → chunk-VIJARDBM.cjs} +3 -3
- package/dist/{chunk-7CZ4MJSI.cjs.map → chunk-VIJARDBM.cjs.map} +1 -1
- package/dist/{chunk-PXXS27EE.cjs → chunk-W24U7ZUV.cjs} +40 -42
- package/dist/chunk-W24U7ZUV.cjs.map +1 -0
- package/dist/{chunk-37ZZQXHK.js → chunk-XPZLIONZ.js} +4 -4
- package/dist/{chunk-FO4CI4R5.cjs → chunk-YCLSV2H6.cjs} +5 -5
- package/dist/{chunk-FO4CI4R5.cjs.map → chunk-YCLSV2H6.cjs.map} +1 -1
- package/dist/{chunk-U7U2CZBZ.js → chunk-Z4N7XLFG.js} +3 -3
- package/dist/components/case-studies/index.cjs +10 -10
- package/dist/components/case-studies/index.js +4 -4
- package/dist/components/chat/hooks/use-chunk-catchup.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-jetstream-dialog-subscription.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +44 -1
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-nats-dialog-subscription.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +10 -4
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.js +9 -3
- package/dist/components/chat/utils/message-segment-accumulator.d.ts.map +1 -1
- package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +5 -5
- package/dist/components/contact/index.js +4 -4
- package/dist/components/docs/index.cjs +7 -7
- package/dist/components/docs/index.js +6 -6
- package/dist/components/embeds/index.cjs +5 -5
- package/dist/components/embeds/index.js +4 -4
- package/dist/components/faq/index.cjs +6 -6
- package/dist/components/faq/index.js +5 -5
- package/dist/components/features/index.cjs +4 -4
- package/dist/components/features/index.js +3 -3
- 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 +142 -136
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +18 -12
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +4 -4
- package/dist/components/navigation/index.js +3 -3
- package/dist/components/onboarding-guides/index.cjs +8 -8
- package/dist/components/onboarding-guides/index.js +7 -7
- package/dist/components/related-content/index.cjs +6 -6
- package/dist/components/related-content/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 +10 -4
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +9 -3
- package/dist/hooks/index.cjs +3 -3
- package/dist/hooks/index.js +2 -2
- package/dist/index.cjs +10 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +9 -3
- package/dist/nats/index.cjs +2 -2
- package/dist/nats/index.js +1 -1
- package/dist/nats/shared-connection.d.ts +6 -0
- package/dist/nats/shared-connection.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/chat/hooks/__tests__/nats-adapter-message-updaters.test.ts +270 -0
- package/src/components/chat/hooks/use-chunk-catchup.ts +212 -57
- package/src/components/chat/hooks/use-jetstream-dialog-subscription.ts +12 -8
- package/src/components/chat/hooks/use-nats-chat-adapter.ts +574 -9
- package/src/components/chat/hooks/use-nats-dialog-subscription.ts +12 -6
- package/src/components/chat/hooks/use-realtime-chunk-processor.ts +40 -3
- package/src/components/chat/utils/__tests__/process-historical-messages-approvals.test.ts +62 -0
- package/src/components/chat/utils/message-segment-accumulator.ts +6 -0
- package/src/components/chat/utils/process-historical-messages.ts +25 -3
- package/src/nats/shared-connection.ts +42 -29
- package/dist/chunk-4R3SVOKH.cjs.map +0 -1
- package/dist/chunk-PHWQLKVE.js.map +0 -1
- package/dist/chunk-PXXS27EE.cjs.map +0 -1
- /package/dist/{chunk-DTMJWBDQ.js.map → chunk-22NSWMI6.js.map} +0 -0
- /package/dist/{chunk-PMTR5W5G.js.map → chunk-3DQ5BFPM.js.map} +0 -0
- /package/dist/{chunk-MG4AMIFX.js.map → chunk-5NYXGWBN.js.map} +0 -0
- /package/dist/{chunk-LCJGOV6P.js.map → chunk-7R256DKK.js.map} +0 -0
- /package/dist/{chunk-3SCNEGL2.js.map → chunk-FIAXFNAA.js.map} +0 -0
- /package/dist/{chunk-FQASXKBK.js.map → chunk-G2KXNMFQ.js.map} +0 -0
- /package/dist/{chunk-H7H3AFLF.js.map → chunk-H2DYCT6M.js.map} +0 -0
- /package/dist/{chunk-CE3AITV2.js.map → chunk-H352AZJN.js.map} +0 -0
- /package/dist/{chunk-DCDB3SM4.js.map → chunk-K4RASNQM.js.map} +0 -0
- /package/dist/{chunk-ABIRMYG5.js.map → chunk-MQUS6BFR.js.map} +0 -0
- /package/dist/{chunk-F2XHBAHT.js.map → chunk-TCEBFMLQ.js.map} +0 -0
- /package/dist/{chunk-37ZZQXHK.js.map → chunk-XPZLIONZ.js.map} +0 -0
- /package/dist/{chunk-U7U2CZBZ.js.map → chunk-Z4N7XLFG.js.map} +0 -0
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
useOgPlaceholderUrl,
|
|
28
28
|
useOnboardingState,
|
|
29
29
|
useToast
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-5NYXGWBN.js";
|
|
31
31
|
import {
|
|
32
32
|
AlertCircleIcon,
|
|
33
33
|
AnthropicLogoGreyIcon,
|
|
@@ -249,7 +249,7 @@ import {
|
|
|
249
249
|
acquireClient,
|
|
250
250
|
releaseClient,
|
|
251
251
|
startConnectionLifecycle
|
|
252
|
-
} from "./chunk-
|
|
252
|
+
} from "./chunk-P47NN7RY.js";
|
|
253
253
|
import {
|
|
254
254
|
__esm
|
|
255
255
|
} from "./chunk-GGWZFCYS.js";
|
|
@@ -46956,8 +46956,10 @@ function useChunkCatchup({
|
|
|
46956
46956
|
}) {
|
|
46957
46957
|
const processedSequenceKeys = useRef64(/* @__PURE__ */ new Set());
|
|
46958
46958
|
const lastSequenceId = useRef64(null);
|
|
46959
|
+
const lastSequenceIdByType = useRef64(/* @__PURE__ */ new Map());
|
|
46959
46960
|
const fetchingInProgress = useRef64(false);
|
|
46960
46961
|
const lastFetchParams = useRef64(null);
|
|
46962
|
+
const pendingCatchupRef = useRef64(null);
|
|
46961
46963
|
const chunkBuffer = useRef64([]);
|
|
46962
46964
|
const bufferUntilInitialCatchupComplete = useRef64(false);
|
|
46963
46965
|
const hasCompletedInitialCatchup = useRef64(false);
|
|
@@ -46976,8 +46978,14 @@ function useChunkCatchup({
|
|
|
46976
46978
|
}
|
|
46977
46979
|
if (chunk.sequenceId !== void 0 && chunk.sequenceId !== null) {
|
|
46978
46980
|
const chunkType = typeof chunk.type === "string" ? chunk.type : "";
|
|
46979
|
-
|
|
46981
|
+
const key = makeSeqKey(messageType, chunkType, chunk.sequenceId);
|
|
46982
|
+
if (processedSequenceKeys.current.has(key)) return true;
|
|
46983
|
+
processedSequenceKeys.current.add(key);
|
|
46980
46984
|
lastSequenceId.current = chunk.sequenceId;
|
|
46985
|
+
const prevTypeSeq = lastSequenceIdByType.current.get(messageType);
|
|
46986
|
+
if (prevTypeSeq === void 0 || chunk.sequenceId > prevTypeSeq) {
|
|
46987
|
+
lastSequenceIdByType.current.set(messageType, chunk.sequenceId);
|
|
46988
|
+
}
|
|
46981
46989
|
}
|
|
46982
46990
|
onChunkReceivedRef.current(chunk, messageType);
|
|
46983
46991
|
return true;
|
|
@@ -46987,8 +46995,8 @@ function useChunkCatchup({
|
|
|
46987
46995
|
const buffered = [...chunkBuffer.current];
|
|
46988
46996
|
chunkBuffer.current = [];
|
|
46989
46997
|
buffered.sort((a, b) => {
|
|
46990
|
-
const seqA = a.chunk.sequenceId ??
|
|
46991
|
-
const seqB = b.chunk.sequenceId ??
|
|
46998
|
+
const seqA = a.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
46999
|
+
const seqB = b.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
46992
47000
|
return seqA - seqB;
|
|
46993
47001
|
});
|
|
46994
47002
|
buffered.forEach(({ chunk, messageType }) => {
|
|
@@ -47003,9 +47011,14 @@ function useChunkCatchup({
|
|
|
47003
47011
|
return;
|
|
47004
47012
|
}
|
|
47005
47013
|
if (hasCompletedInitialCatchup.current) {
|
|
47014
|
+
if (bufferUntilInitialCatchupComplete.current) {
|
|
47015
|
+
bufferUntilInitialCatchupComplete.current = false;
|
|
47016
|
+
flushBufferedRealtimeChunks();
|
|
47017
|
+
}
|
|
47006
47018
|
return;
|
|
47007
47019
|
}
|
|
47008
47020
|
if (fetchingInProgress.current) {
|
|
47021
|
+
pendingCatchupRef.current = { dialogId: dialogId2, fromSequenceId: fromSequenceId ?? lastSequenceId.current };
|
|
47009
47022
|
return;
|
|
47010
47023
|
}
|
|
47011
47024
|
if (lastFetchParams.current && lastFetchParams.current.dialogId === dialogId2 && lastFetchParams.current.fromSequenceId === fromSequenceId) {
|
|
@@ -47022,7 +47035,8 @@ function useChunkCatchup({
|
|
|
47022
47035
|
try {
|
|
47023
47036
|
const chunkPromises = chatTypes2.map(async (chatType) => {
|
|
47024
47037
|
try {
|
|
47025
|
-
const
|
|
47038
|
+
const typeFromSequenceId = fromSequenceId === void 0 ? void 0 : lastSequenceIdByType.current.get(getChatTypeMessageType(chatType)) ?? null;
|
|
47039
|
+
const chunks = await fetchChunks2(dialogId2, chatType, typeFromSequenceId);
|
|
47026
47040
|
const messageType = getChatTypeMessageType(chatType);
|
|
47027
47041
|
return chunks.map((chunk) => ({ chunk, messageType }));
|
|
47028
47042
|
} catch (error) {
|
|
@@ -47042,49 +47056,66 @@ function useChunkCatchup({
|
|
|
47042
47056
|
chunkBuffer.current = [];
|
|
47043
47057
|
const allChunks = [...allCatchupChunks, ...bufferedNatsChunks];
|
|
47044
47058
|
allChunks.sort((a, b) => {
|
|
47045
|
-
const seqA = a.chunk.sequenceId ??
|
|
47046
|
-
const seqB = b.chunk.sequenceId ??
|
|
47059
|
+
const seqA = a.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
47060
|
+
const seqB = b.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
47047
47061
|
return seqA - seqB;
|
|
47048
47062
|
});
|
|
47049
47063
|
const uniqueAllChunks = [];
|
|
47050
47064
|
const seenInBatch = /* @__PURE__ */ new Set();
|
|
47051
47065
|
for (const item of allChunks) {
|
|
47052
|
-
const
|
|
47053
|
-
if (
|
|
47054
|
-
|
|
47055
|
-
|
|
47056
|
-
|
|
47057
|
-
let lastMessageStartSeqId = null;
|
|
47058
|
-
let lastMessageEndSeqId = null;
|
|
47059
|
-
for (let i = uniqueAllChunks.length - 1; i >= 0; i--) {
|
|
47060
|
-
const seq = uniqueAllChunks[i].chunk.sequenceId;
|
|
47061
|
-
if (uniqueAllChunks[i].chunk.type === MESSAGE_TYPE.MESSAGE_END && seq !== void 0 && seq !== null) {
|
|
47062
|
-
lastMessageEndSeqId = seq;
|
|
47063
|
-
break;
|
|
47066
|
+
const hasSeq = item.chunk.sequenceId !== void 0 && item.chunk.sequenceId !== null;
|
|
47067
|
+
if (hasSeq) {
|
|
47068
|
+
const k = makeBatchDedupKey(item);
|
|
47069
|
+
if (seenInBatch.has(k)) continue;
|
|
47070
|
+
seenInBatch.add(k);
|
|
47064
47071
|
}
|
|
47072
|
+
uniqueAllChunks.push(item);
|
|
47065
47073
|
}
|
|
47066
|
-
|
|
47067
|
-
|
|
47068
|
-
|
|
47069
|
-
|
|
47070
|
-
|
|
47071
|
-
|
|
47074
|
+
const hasNoSeq = (item) => item.chunk.sequenceId === void 0 || item.chunk.sequenceId === null;
|
|
47075
|
+
const byType = /* @__PURE__ */ new Map();
|
|
47076
|
+
for (const item of uniqueAllChunks) {
|
|
47077
|
+
const list = byType.get(item.messageType);
|
|
47078
|
+
if (list) list.push(item);
|
|
47079
|
+
else byType.set(item.messageType, [item]);
|
|
47080
|
+
}
|
|
47081
|
+
const chunksToProcess = [];
|
|
47082
|
+
for (const items of byType.values()) {
|
|
47083
|
+
let lastMessageStartSeqId = null;
|
|
47084
|
+
let lastMessageEndSeqId = null;
|
|
47085
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
47086
|
+
const seq = items[i].chunk.sequenceId;
|
|
47087
|
+
if (items[i].chunk.type === MESSAGE_TYPE.MESSAGE_END && seq !== void 0 && seq !== null) {
|
|
47088
|
+
lastMessageEndSeqId = seq;
|
|
47072
47089
|
break;
|
|
47073
47090
|
}
|
|
47074
47091
|
}
|
|
47092
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
47093
|
+
const chunk = items[i].chunk;
|
|
47094
|
+
const seq = chunk.sequenceId;
|
|
47095
|
+
if (chunk.type === MESSAGE_TYPE.MESSAGE_START && seq !== void 0 && seq !== null) {
|
|
47096
|
+
if (lastMessageEndSeqId === null || seq > lastMessageEndSeqId) {
|
|
47097
|
+
lastMessageStartSeqId = seq;
|
|
47098
|
+
break;
|
|
47099
|
+
}
|
|
47100
|
+
}
|
|
47101
|
+
}
|
|
47102
|
+
if (lastMessageStartSeqId !== null) {
|
|
47103
|
+
chunksToProcess.push(
|
|
47104
|
+
...items.filter((item) => hasNoSeq(item) || item.chunk.sequenceId >= lastMessageStartSeqId)
|
|
47105
|
+
);
|
|
47106
|
+
} else if (lastMessageEndSeqId !== null) {
|
|
47107
|
+
chunksToProcess.push(
|
|
47108
|
+
...items.filter((item) => hasNoSeq(item) || item.chunk.sequenceId > lastMessageEndSeqId)
|
|
47109
|
+
);
|
|
47110
|
+
} else {
|
|
47111
|
+
chunksToProcess.push(...items);
|
|
47112
|
+
}
|
|
47075
47113
|
}
|
|
47076
|
-
|
|
47077
|
-
|
|
47078
|
-
|
|
47079
|
-
|
|
47080
|
-
|
|
47081
|
-
} else if (lastMessageEndSeqId !== null) {
|
|
47082
|
-
chunksToProcess = uniqueAllChunks.filter(
|
|
47083
|
-
(item) => item.chunk.sequenceId !== void 0 && item.chunk.sequenceId > lastMessageEndSeqId
|
|
47084
|
-
);
|
|
47085
|
-
} else {
|
|
47086
|
-
chunksToProcess = uniqueAllChunks;
|
|
47087
|
-
}
|
|
47114
|
+
chunksToProcess.sort((a, b) => {
|
|
47115
|
+
const seqA = a.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
47116
|
+
const seqB = b.chunk.sequenceId ?? Number.MAX_SAFE_INTEGER;
|
|
47117
|
+
return seqA - seqB;
|
|
47118
|
+
});
|
|
47088
47119
|
chunksToProcess.forEach(({ chunk, messageType }) => {
|
|
47089
47120
|
if (chunk.sequenceId !== void 0 && chunk.sequenceId !== null) {
|
|
47090
47121
|
const chunkType = typeof chunk.type === "string" ? chunk.type : "";
|
|
@@ -47092,6 +47123,10 @@ function useChunkCatchup({
|
|
|
47092
47123
|
if (processedSequenceKeys.current.has(key)) return;
|
|
47093
47124
|
processedSequenceKeys.current.add(key);
|
|
47094
47125
|
lastSequenceId.current = chunk.sequenceId;
|
|
47126
|
+
const prevTypeSeq = lastSequenceIdByType.current.get(messageType);
|
|
47127
|
+
if (prevTypeSeq === void 0 || chunk.sequenceId > prevTypeSeq) {
|
|
47128
|
+
lastSequenceIdByType.current.set(messageType, chunk.sequenceId);
|
|
47129
|
+
}
|
|
47095
47130
|
}
|
|
47096
47131
|
onChunkReceivedRef.current(chunk, messageType);
|
|
47097
47132
|
});
|
|
@@ -47100,26 +47135,55 @@ function useChunkCatchup({
|
|
|
47100
47135
|
} catch (error) {
|
|
47101
47136
|
console.error("Error during chunk catchup:", error);
|
|
47102
47137
|
} finally {
|
|
47103
|
-
|
|
47104
|
-
|
|
47105
|
-
|
|
47106
|
-
|
|
47107
|
-
|
|
47138
|
+
if (dialogId2 !== dialogIdRef.current) {
|
|
47139
|
+
if (pendingCatchupRef.current?.dialogId === dialogId2) {
|
|
47140
|
+
pendingCatchupRef.current = null;
|
|
47141
|
+
}
|
|
47142
|
+
} else {
|
|
47143
|
+
fetchingInProgress.current = false;
|
|
47144
|
+
const pending = pendingCatchupRef.current;
|
|
47145
|
+
if (pending) {
|
|
47146
|
+
pendingCatchupRef.current = null;
|
|
47147
|
+
if (pending.dialogId === dialogId2) {
|
|
47148
|
+
hasCompletedInitialCatchup.current = false;
|
|
47149
|
+
lastFetchParams.current = null;
|
|
47150
|
+
bufferUntilInitialCatchupComplete.current = true;
|
|
47151
|
+
try {
|
|
47152
|
+
await catchUpChunksRef.current?.(pending.fromSequenceId);
|
|
47153
|
+
} catch (rerunError) {
|
|
47154
|
+
console.error("Queued catch-up re-run failed:", rerunError);
|
|
47155
|
+
}
|
|
47156
|
+
} else if (bufferUntilInitialCatchupComplete.current) {
|
|
47157
|
+
bufferUntilInitialCatchupComplete.current = false;
|
|
47158
|
+
hasCompletedInitialCatchup.current = true;
|
|
47159
|
+
flushBufferedRealtimeChunks();
|
|
47160
|
+
}
|
|
47161
|
+
} else if (bufferUntilInitialCatchupComplete.current) {
|
|
47162
|
+
bufferUntilInitialCatchupComplete.current = false;
|
|
47163
|
+
hasCompletedInitialCatchup.current = true;
|
|
47164
|
+
flushBufferedRealtimeChunks();
|
|
47165
|
+
}
|
|
47108
47166
|
}
|
|
47109
47167
|
}
|
|
47110
47168
|
}, [flushBufferedRealtimeChunks]);
|
|
47169
|
+
const catchUpChunksRef = useRef64(null);
|
|
47170
|
+
catchUpChunksRef.current = catchUpChunks;
|
|
47111
47171
|
const resetChunkTracking = useCallback46(() => {
|
|
47112
47172
|
processedSequenceKeys.current.clear();
|
|
47113
47173
|
lastSequenceId.current = null;
|
|
47174
|
+
lastSequenceIdByType.current.clear();
|
|
47114
47175
|
fetchingInProgress.current = false;
|
|
47115
47176
|
lastFetchParams.current = null;
|
|
47177
|
+
pendingCatchupRef.current = null;
|
|
47116
47178
|
chunkBuffer.current = [];
|
|
47117
47179
|
bufferUntilInitialCatchupComplete.current = false;
|
|
47118
47180
|
hasCompletedInitialCatchup.current = false;
|
|
47119
47181
|
}, []);
|
|
47120
47182
|
const startInitialBuffering = useCallback46(() => {
|
|
47121
|
-
|
|
47122
|
-
|
|
47183
|
+
if (!bufferUntilInitialCatchupComplete.current) {
|
|
47184
|
+
chunkBuffer.current = [];
|
|
47185
|
+
bufferUntilInitialCatchupComplete.current = true;
|
|
47186
|
+
}
|
|
47123
47187
|
hasCompletedInitialCatchup.current = false;
|
|
47124
47188
|
}, []);
|
|
47125
47189
|
const isBufferingActive = useCallback46(() => bufferUntilInitialCatchupComplete.current, []);
|
|
@@ -47128,8 +47192,10 @@ function useChunkCatchup({
|
|
|
47128
47192
|
const fromSeq = lastSequenceId.current;
|
|
47129
47193
|
hasCompletedInitialCatchup.current = false;
|
|
47130
47194
|
lastFetchParams.current = null;
|
|
47131
|
-
bufferUntilInitialCatchupComplete.current
|
|
47132
|
-
|
|
47195
|
+
if (!bufferUntilInitialCatchupComplete.current) {
|
|
47196
|
+
chunkBuffer.current = [];
|
|
47197
|
+
bufferUntilInitialCatchupComplete.current = true;
|
|
47198
|
+
}
|
|
47133
47199
|
await catchUpChunks(fromSeq);
|
|
47134
47200
|
}, [catchUpChunks]);
|
|
47135
47201
|
return {
|
|
@@ -47329,6 +47395,10 @@ function useJetStreamDialogSubscription({
|
|
|
47329
47395
|
}
|
|
47330
47396
|
};
|
|
47331
47397
|
}, [enabled, wsUrl]);
|
|
47398
|
+
useEffect79(() => {
|
|
47399
|
+
highestStreamSeqRef.current = null;
|
|
47400
|
+
setCurrentStreamSeq(null);
|
|
47401
|
+
}, [dialogId]);
|
|
47332
47402
|
useEffect79(() => {
|
|
47333
47403
|
if (!enabled || !dialogId || !isConnected) {
|
|
47334
47404
|
if (subscriptionRef.current) {
|
|
@@ -47412,10 +47482,6 @@ function useJetStreamDialogSubscription({
|
|
|
47412
47482
|
setIsSubscribed(false);
|
|
47413
47483
|
};
|
|
47414
47484
|
}, [enabled, dialogId, isConnected, streamName, topic, reconnectionCount]);
|
|
47415
|
-
useEffect79(() => {
|
|
47416
|
-
highestStreamSeqRef.current = null;
|
|
47417
|
-
setCurrentStreamSeq(null);
|
|
47418
|
-
}, [dialogId]);
|
|
47419
47485
|
return { isConnected, isSubscribed, reconnectionCount, currentStreamSeq };
|
|
47420
47486
|
}
|
|
47421
47487
|
|
|
@@ -47556,6 +47622,8 @@ function useNatsDialogSubscription({
|
|
|
47556
47622
|
};
|
|
47557
47623
|
}, [enabled, wsUrl]);
|
|
47558
47624
|
const topicsKey = topics.join(",");
|
|
47625
|
+
const topicsRef = useRef66(topics);
|
|
47626
|
+
topicsRef.current = topics;
|
|
47559
47627
|
const lastSubscribedDialogIdRef = useRef66(null);
|
|
47560
47628
|
const isConnectedRef = useRef66(isConnected);
|
|
47561
47629
|
useEffect80(() => {
|
|
@@ -47615,7 +47683,7 @@ function useNatsDialogSubscription({
|
|
|
47615
47683
|
} catch {
|
|
47616
47684
|
}
|
|
47617
47685
|
};
|
|
47618
|
-
|
|
47686
|
+
topicsRef.current.forEach((topic) => {
|
|
47619
47687
|
const subscription = client.subscribeBytes(
|
|
47620
47688
|
`chat.${dialogId}.${topic}`,
|
|
47621
47689
|
handleMessage(topic),
|
|
@@ -47643,7 +47711,7 @@ function useNatsDialogSubscription({
|
|
|
47643
47711
|
lastSubscribedDialogIdRef.current = null;
|
|
47644
47712
|
abortControllerRef.current = null;
|
|
47645
47713
|
};
|
|
47646
|
-
}, [enabled, dialogId, topicsKey
|
|
47714
|
+
}, [enabled, dialogId, topicsKey]);
|
|
47647
47715
|
useEffect80(() => {
|
|
47648
47716
|
if (!enabled || !currentDialogIdRef.current || !isConnected) {
|
|
47649
47717
|
return;
|
|
@@ -47666,7 +47734,7 @@ function useNatsDialogSubscription({
|
|
|
47666
47734
|
} catch {
|
|
47667
47735
|
}
|
|
47668
47736
|
};
|
|
47669
|
-
|
|
47737
|
+
topicsRef.current.forEach((topic) => {
|
|
47670
47738
|
const subscription = client.subscribeBytes(
|
|
47671
47739
|
`chat.${dialogId2}.${topic}`,
|
|
47672
47740
|
handleMessage(topic),
|
|
@@ -47680,7 +47748,7 @@ function useNatsDialogSubscription({
|
|
|
47680
47748
|
} else if (subscriptionRefs.current.size > 0) {
|
|
47681
47749
|
setIsSubscribed(true);
|
|
47682
47750
|
}
|
|
47683
|
-
}, [isConnected, enabled,
|
|
47751
|
+
}, [isConnected, enabled, topicsKey]);
|
|
47684
47752
|
return { isConnected, isSubscribed, reconnectionCount };
|
|
47685
47753
|
}
|
|
47686
47754
|
function buildNatsWsUrl(apiBaseUrl, options) {
|
|
@@ -48041,6 +48109,10 @@ var MessageSegmentAccumulator = class {
|
|
|
48041
48109
|
const hasCall = seg.data.toolCalls.some((c) => c.toolExecutionRequestId === execId);
|
|
48042
48110
|
if (!hasCall) return seg;
|
|
48043
48111
|
const prev = seg.data.executions?.[execId];
|
|
48112
|
+
if (toolData.type === "EXECUTING_TOOL" && prev?.status === "done") {
|
|
48113
|
+
matched = true;
|
|
48114
|
+
return seg;
|
|
48115
|
+
}
|
|
48044
48116
|
const next = toolData.type === "EXECUTED_TOOL" ? { status: "done", result: toolData.result, success: toolData.success } : { status: "executing", result: prev?.result, success: prev?.success };
|
|
48045
48117
|
matched = true;
|
|
48046
48118
|
return {
|
|
@@ -48504,6 +48576,16 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48504
48576
|
explanation: escalatedData.explanation,
|
|
48505
48577
|
approvalType: escalatedData.approvalType
|
|
48506
48578
|
});
|
|
48579
|
+
const emitResolved = (segments) => {
|
|
48580
|
+
if (isInStreamRef.current) {
|
|
48581
|
+
emitSegments(segments);
|
|
48582
|
+
return;
|
|
48583
|
+
}
|
|
48584
|
+
const delta = segments.filter(
|
|
48585
|
+
(s) => s.type === "approval_request" && s.data.requestId === requestId || s.type === "approval_batch" && s.data.approvalRequestId === requestId
|
|
48586
|
+
);
|
|
48587
|
+
emitSegments(delta, { append: true });
|
|
48588
|
+
};
|
|
48507
48589
|
if (escalatedData.toolCalls && escalatedData.toolCalls.length > 0) {
|
|
48508
48590
|
if (batchApprovalsEnabled) {
|
|
48509
48591
|
const segments = accumulator.addApprovalBatch(
|
|
@@ -48514,7 +48596,7 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48514
48596
|
void 0,
|
|
48515
48597
|
resolvedByName
|
|
48516
48598
|
);
|
|
48517
|
-
|
|
48599
|
+
emitResolved(segments);
|
|
48518
48600
|
} else {
|
|
48519
48601
|
let segments = accumulator.getSegments();
|
|
48520
48602
|
for (const call of escalatedData.toolCalls) {
|
|
@@ -48527,7 +48609,7 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48527
48609
|
status
|
|
48528
48610
|
);
|
|
48529
48611
|
}
|
|
48530
|
-
|
|
48612
|
+
emitResolved(segments);
|
|
48531
48613
|
}
|
|
48532
48614
|
} else {
|
|
48533
48615
|
const segments = accumulator.addApprovalRequest(
|
|
@@ -48537,7 +48619,7 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48537
48619
|
escalatedData.approvalType,
|
|
48538
48620
|
status
|
|
48539
48621
|
);
|
|
48540
|
-
|
|
48622
|
+
emitResolved(segments);
|
|
48541
48623
|
}
|
|
48542
48624
|
} else {
|
|
48543
48625
|
accumulator.updateApprovalStatus(requestId, status, resolvedByName);
|
|
@@ -48617,6 +48699,8 @@ function useRealtimeChunkProcessor(options) {
|
|
|
48617
48699
|
hasInitializedWithData.current = false;
|
|
48618
48700
|
sawDirectMessageRef.current = false;
|
|
48619
48701
|
directTeardownFiredRef.current = false;
|
|
48702
|
+
isInStreamRef.current = false;
|
|
48703
|
+
hasEverStreamedRef.current = false;
|
|
48620
48704
|
}, []);
|
|
48621
48705
|
const updateApprovalStatus = useCallback47(
|
|
48622
48706
|
(requestId, status, resolvedByName) => {
|
|
@@ -50147,7 +50231,15 @@ function processHistoricalMessages(messages, options = {}) {
|
|
|
50147
50231
|
onReject,
|
|
50148
50232
|
chatTypeFilter,
|
|
50149
50233
|
approvalStatuses = {},
|
|
50150
|
-
|
|
50234
|
+
// An omitted option means "display every approval type" — the original
|
|
50235
|
+
// history semantics. Deliberately NOT defaulted to the realtime
|
|
50236
|
+
// processor's ['CLIENT']: consumers that pass a wider list to their
|
|
50237
|
+
// realtime processor but omit it on the history path would silently lose
|
|
50238
|
+
// pending non-CLIENT approval cards on every reload/reconnect refetch
|
|
50239
|
+
// (they also ignore `escalatedApprovals`). Realtime/history parity is
|
|
50240
|
+
// opt-in: pass the same explicit list to both.
|
|
50241
|
+
displayApprovalTypes,
|
|
50242
|
+
batchApprovalsEnabled
|
|
50151
50243
|
} = options;
|
|
50152
50244
|
const processedMessages = [];
|
|
50153
50245
|
const accumulator = createMessageSegmentAccumulator({ onApprove, onReject });
|
|
@@ -50212,7 +50304,13 @@ function processHistoricalMessages(messages, options = {}) {
|
|
|
50212
50304
|
}
|
|
50213
50305
|
lastAssistantId = msg.id;
|
|
50214
50306
|
messageDataArray.forEach((data) => {
|
|
50215
|
-
processMessageData(
|
|
50307
|
+
processMessageData(
|
|
50308
|
+
data,
|
|
50309
|
+
accumulator,
|
|
50310
|
+
approvalStatuses,
|
|
50311
|
+
{ displayApprovalTypes, batchApprovalsEnabled },
|
|
50312
|
+
escalatedApprovals
|
|
50313
|
+
);
|
|
50216
50314
|
});
|
|
50217
50315
|
const nextMsg = messages[index + 1];
|
|
50218
50316
|
const isLastMessage = index === messages.length - 1;
|
|
@@ -50436,7 +50534,7 @@ function extractErrorMessages(messages, options = {}) {
|
|
|
50436
50534
|
return errorMessages;
|
|
50437
50535
|
}
|
|
50438
50536
|
function processHistoricalMessagesWithErrors(messages, options = {}) {
|
|
50439
|
-
const { chatTypeFilter, assistantName = "Fae", assistantType = "fae", assistantAvatar, onApprove, onReject, approvalStatuses = {}, displayApprovalTypes } = options;
|
|
50537
|
+
const { chatTypeFilter, assistantName = "Fae", assistantType = "fae", assistantAvatar, onApprove, onReject, approvalStatuses = {}, displayApprovalTypes, batchApprovalsEnabled } = options;
|
|
50440
50538
|
const processedMessages = [];
|
|
50441
50539
|
const accumulator = createMessageSegmentAccumulator({ onApprove, onReject });
|
|
50442
50540
|
const escalatedApprovals = /* @__PURE__ */ new Map();
|
|
@@ -50500,7 +50598,13 @@ function processHistoricalMessagesWithErrors(messages, options = {}) {
|
|
|
50500
50598
|
}
|
|
50501
50599
|
lastAssistantId = msg.id;
|
|
50502
50600
|
messageDataArray.forEach((data) => {
|
|
50503
|
-
processMessageData(
|
|
50601
|
+
processMessageData(
|
|
50602
|
+
data,
|
|
50603
|
+
accumulator,
|
|
50604
|
+
approvalStatuses,
|
|
50605
|
+
{ displayApprovalTypes, batchApprovalsEnabled },
|
|
50606
|
+
escalatedApprovals
|
|
50607
|
+
);
|
|
50504
50608
|
});
|
|
50505
50609
|
const nextMsg = messages[index + 1];
|
|
50506
50610
|
const isLastMessage = index === messages.length - 1;
|
|
@@ -50529,6 +50633,65 @@ function processHistoricalMessagesWithErrors(messages, options = {}) {
|
|
|
50529
50633
|
};
|
|
50530
50634
|
}
|
|
50531
50635
|
|
|
50636
|
+
// src/components/chat/utils/extract-incomplete-message-state.ts
|
|
50637
|
+
function extractIncompleteMessageState(lastMessage) {
|
|
50638
|
+
if (!lastMessage || lastMessage.role !== "assistant" || typeof lastMessage.content === "string") {
|
|
50639
|
+
return void 0;
|
|
50640
|
+
}
|
|
50641
|
+
const segments = lastMessage.content;
|
|
50642
|
+
const pendingApprovals = /* @__PURE__ */ new Map();
|
|
50643
|
+
const executingTools = /* @__PURE__ */ new Map();
|
|
50644
|
+
let hasIncompleteState = false;
|
|
50645
|
+
segments.forEach((segment) => {
|
|
50646
|
+
switch (segment.type) {
|
|
50647
|
+
case "tool_execution":
|
|
50648
|
+
if (segment.data.type === "EXECUTING_TOOL") {
|
|
50649
|
+
const toolKey = segment.data.toolExecutionRequestId || `${segment.data.integratedToolType}-${segment.data.toolFunction}`;
|
|
50650
|
+
executingTools.set(toolKey, {
|
|
50651
|
+
integratedToolType: segment.data.integratedToolType,
|
|
50652
|
+
toolFunction: segment.data.toolFunction,
|
|
50653
|
+
toolTitle: segment.data.toolTitle,
|
|
50654
|
+
parameters: segment.data.parameters
|
|
50655
|
+
});
|
|
50656
|
+
hasIncompleteState = true;
|
|
50657
|
+
}
|
|
50658
|
+
break;
|
|
50659
|
+
case "approval_request":
|
|
50660
|
+
if (segment.status === "pending" && segment.data.requestId) {
|
|
50661
|
+
pendingApprovals.set(segment.data.requestId, {
|
|
50662
|
+
command: segment.data.command,
|
|
50663
|
+
explanation: segment.data.explanation,
|
|
50664
|
+
approvalType: segment.data.approvalType || "CLIENT"
|
|
50665
|
+
});
|
|
50666
|
+
hasIncompleteState = true;
|
|
50667
|
+
}
|
|
50668
|
+
break;
|
|
50669
|
+
case "approval_batch": {
|
|
50670
|
+
const allDone = !!segment.data.executions && segment.data.toolCalls.every(
|
|
50671
|
+
(c) => segment.data.executions?.[c.toolExecutionRequestId]?.status === "done"
|
|
50672
|
+
);
|
|
50673
|
+
if (segment.status !== "rejected" && !allDone) {
|
|
50674
|
+
hasIncompleteState = true;
|
|
50675
|
+
}
|
|
50676
|
+
break;
|
|
50677
|
+
}
|
|
50678
|
+
case "context_compaction":
|
|
50679
|
+
if (segment.status === "started") {
|
|
50680
|
+
hasIncompleteState = true;
|
|
50681
|
+
}
|
|
50682
|
+
break;
|
|
50683
|
+
}
|
|
50684
|
+
});
|
|
50685
|
+
if (!hasIncompleteState) {
|
|
50686
|
+
return void 0;
|
|
50687
|
+
}
|
|
50688
|
+
return {
|
|
50689
|
+
existingSegments: segments,
|
|
50690
|
+
pendingApprovals: pendingApprovals.size > 0 ? pendingApprovals : void 0,
|
|
50691
|
+
executingTools: executingTools.size > 0 ? executingTools : void 0
|
|
50692
|
+
};
|
|
50693
|
+
}
|
|
50694
|
+
|
|
50532
50695
|
// src/components/chat/hooks/use-nats-chat-adapter.ts
|
|
50533
50696
|
function nextId(role) {
|
|
50534
50697
|
return `${role}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
@@ -50551,6 +50714,110 @@ function updateTrailingAssistant(prev, segments) {
|
|
|
50551
50714
|
{ ...last, segments }
|
|
50552
50715
|
];
|
|
50553
50716
|
}
|
|
50717
|
+
var CONTENT_DEDUP_WINDOW = 4;
|
|
50718
|
+
var SYSTEM_DEDUP_WINDOW = 10;
|
|
50719
|
+
function hasRecentMessage(prev, predicate, window2) {
|
|
50720
|
+
const start = Math.max(0, prev.length - window2);
|
|
50721
|
+
for (let i = prev.length - 1; i >= start; i--) {
|
|
50722
|
+
if (predicate(prev[i])) return true;
|
|
50723
|
+
}
|
|
50724
|
+
return false;
|
|
50725
|
+
}
|
|
50726
|
+
function appendToTrailingAssistant(prev, segments) {
|
|
50727
|
+
if (segments.length === 0) return prev;
|
|
50728
|
+
const last = prev[prev.length - 1];
|
|
50729
|
+
if (!last || last.role !== "assistant") {
|
|
50730
|
+
return [
|
|
50731
|
+
...prev,
|
|
50732
|
+
{ id: nextId("assistant"), role: "assistant", content: "", segments }
|
|
50733
|
+
];
|
|
50734
|
+
}
|
|
50735
|
+
const merged = [...last.segments ?? []];
|
|
50736
|
+
for (const seg of segments) {
|
|
50737
|
+
const tail = merged[merged.length - 1];
|
|
50738
|
+
if (seg.type === "text" && tail?.type === "text") {
|
|
50739
|
+
merged[merged.length - 1] = { type: "text", text: tail.text + seg.text };
|
|
50740
|
+
} else if (seg.type === "thinking" && tail?.type === "thinking") {
|
|
50741
|
+
merged[merged.length - 1] = { type: "thinking", text: tail.text + seg.text };
|
|
50742
|
+
} else if (seg.type === "approval_batch") {
|
|
50743
|
+
const idx = merged.findIndex(
|
|
50744
|
+
(m) => m.type === "approval_batch" && m.data.approvalRequestId === seg.data.approvalRequestId
|
|
50745
|
+
);
|
|
50746
|
+
if (idx !== -1) merged[idx] = seg;
|
|
50747
|
+
else merged.push(seg);
|
|
50748
|
+
} else if (seg.type === "approval_request") {
|
|
50749
|
+
const idx = merged.findIndex(
|
|
50750
|
+
(m) => m.type === "approval_request" && m.data.requestId === seg.data.requestId && m.data.command === seg.data.command
|
|
50751
|
+
);
|
|
50752
|
+
if (idx !== -1) merged[idx] = seg;
|
|
50753
|
+
else merged.push(seg);
|
|
50754
|
+
} else {
|
|
50755
|
+
merged.push(seg);
|
|
50756
|
+
}
|
|
50757
|
+
}
|
|
50758
|
+
return [...prev.slice(0, -1), { ...last, segments: merged }];
|
|
50759
|
+
}
|
|
50760
|
+
function upsertTrailingCompaction(prev, segments) {
|
|
50761
|
+
const compaction = [...segments].reverse().find((s) => s.type === "context_compaction");
|
|
50762
|
+
if (!compaction) return prev;
|
|
50763
|
+
const last = prev[prev.length - 1];
|
|
50764
|
+
if (!last || last.role !== "assistant") {
|
|
50765
|
+
return [
|
|
50766
|
+
...prev,
|
|
50767
|
+
{ id: nextId("assistant"), role: "assistant", content: "", segments: [compaction] }
|
|
50768
|
+
];
|
|
50769
|
+
}
|
|
50770
|
+
const existing = last.segments ?? [];
|
|
50771
|
+
const startedIdx = existing.map((s) => s.type === "context_compaction" && s.status === "started").lastIndexOf(true);
|
|
50772
|
+
const merged = startedIdx !== -1 ? existing.map((s, i) => i === startedIdx ? compaction : s) : [...existing, compaction];
|
|
50773
|
+
return [...prev.slice(0, -1), { ...last, segments: merged }];
|
|
50774
|
+
}
|
|
50775
|
+
function applyToolExecutionToMessages(prev, segment) {
|
|
50776
|
+
const toolData = segment.data;
|
|
50777
|
+
const execId = toolData.toolExecutionRequestId;
|
|
50778
|
+
for (let i = prev.length - 1; i >= 0; i--) {
|
|
50779
|
+
const message2 = prev[i];
|
|
50780
|
+
if (message2.role !== "assistant" || !message2.segments) continue;
|
|
50781
|
+
for (let j = message2.segments.length - 1; j >= 0; j--) {
|
|
50782
|
+
const seg = message2.segments[j];
|
|
50783
|
+
if (execId && seg.type === "approval_batch" && seg.data.toolCalls.some((c) => c.toolExecutionRequestId === execId)) {
|
|
50784
|
+
const prevExec = seg.data.executions?.[execId];
|
|
50785
|
+
if (toolData.type === "EXECUTING_TOOL" && prevExec?.status === "done") {
|
|
50786
|
+
return prev;
|
|
50787
|
+
}
|
|
50788
|
+
const nextExec = toolData.type === "EXECUTED_TOOL" ? { status: "done", result: toolData.result, success: toolData.success } : { status: "executing", result: prevExec?.result, success: prevExec?.success };
|
|
50789
|
+
const nextSegments = [...message2.segments];
|
|
50790
|
+
nextSegments[j] = {
|
|
50791
|
+
...seg,
|
|
50792
|
+
data: { ...seg.data, executions: { ...seg.data.executions ?? {}, [execId]: nextExec } }
|
|
50793
|
+
};
|
|
50794
|
+
const next = [...prev];
|
|
50795
|
+
next[i] = { ...message2, segments: nextSegments };
|
|
50796
|
+
return next;
|
|
50797
|
+
}
|
|
50798
|
+
if (seg.type === "tool_execution") {
|
|
50799
|
+
const matches = execId ? seg.data.toolExecutionRequestId === execId : seg.data.type === "EXECUTING_TOOL" && seg.data.integratedToolType === toolData.integratedToolType && seg.data.toolFunction === toolData.toolFunction;
|
|
50800
|
+
if (!matches) continue;
|
|
50801
|
+
if (toolData.type === "EXECUTING_TOOL" && seg.data.type === "EXECUTED_TOOL") {
|
|
50802
|
+
return prev;
|
|
50803
|
+
}
|
|
50804
|
+
const nextSegments = [...message2.segments];
|
|
50805
|
+
nextSegments[j] = {
|
|
50806
|
+
type: "tool_execution",
|
|
50807
|
+
data: {
|
|
50808
|
+
...toolData,
|
|
50809
|
+
toolTitle: toolData.toolTitle ?? seg.data.toolTitle,
|
|
50810
|
+
parameters: toolData.parameters || seg.data.parameters
|
|
50811
|
+
}
|
|
50812
|
+
};
|
|
50813
|
+
const next = [...prev];
|
|
50814
|
+
next[i] = { ...message2, segments: nextSegments };
|
|
50815
|
+
return next;
|
|
50816
|
+
}
|
|
50817
|
+
}
|
|
50818
|
+
}
|
|
50819
|
+
return appendToTrailingAssistant(prev, [segment]);
|
|
50820
|
+
}
|
|
50554
50821
|
function mapProcessedToUnified(processed) {
|
|
50555
50822
|
const out = [];
|
|
50556
50823
|
for (const m of processed) {
|
|
@@ -50590,6 +50857,7 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50590
50857
|
fetchChunks,
|
|
50591
50858
|
topics,
|
|
50592
50859
|
batchApprovalsEnabled,
|
|
50860
|
+
displayApprovalTypes,
|
|
50593
50861
|
fetchDialogs,
|
|
50594
50862
|
fetchDialogMessages,
|
|
50595
50863
|
createDialog: createDialogCallback,
|
|
@@ -50609,11 +50877,17 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50609
50877
|
const isManagedMode = fetchDialogs !== void 0;
|
|
50610
50878
|
const [internalDialogId, setInternalDialogId] = useState116(null);
|
|
50611
50879
|
const dialogId = isManagedMode ? internalDialogId : controlledDialogId !== void 0 ? controlledDialogId : null;
|
|
50880
|
+
const currentDialogIdRef = useRef74(dialogId);
|
|
50881
|
+
currentDialogIdRef.current = dialogId;
|
|
50612
50882
|
const [messages, setMessages] = useState116([]);
|
|
50613
50883
|
const [streamingPhase, setStreamingPhase] = useState116("idle");
|
|
50614
50884
|
const streamingPhaseRef = useRef74(streamingPhase);
|
|
50615
50885
|
streamingPhaseRef.current = streamingPhase;
|
|
50616
|
-
const suppressAgentBusyRef = useRef74(
|
|
50886
|
+
const suppressAgentBusyRef = useRef74(0);
|
|
50887
|
+
const adoptTrailingAssistantRef = useRef74(false);
|
|
50888
|
+
const hasConnectedOnceRef = useRef74(false);
|
|
50889
|
+
const seenParticipantSeqsRef = useRef74(/* @__PURE__ */ new Set());
|
|
50890
|
+
const pendingEchoTextsRef = useRef74([]);
|
|
50617
50891
|
const [approvalStatuses, setApprovalStatuses] = useState116({});
|
|
50618
50892
|
const [dialogs, setDialogs] = useState116([]);
|
|
50619
50893
|
const [dialogsNextCursor, setDialogsNextCursor] = useState116(null);
|
|
@@ -50679,17 +50953,39 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50679
50953
|
return handleRejectRef.current(requestId);
|
|
50680
50954
|
}, []);
|
|
50681
50955
|
const callbacksRef = useRef74({
|
|
50682
|
-
onSegmentsUpdate: (segments) => {
|
|
50956
|
+
onSegmentsUpdate: (segments, meta) => {
|
|
50957
|
+
if (meta?.append && meta.isCompacting) {
|
|
50958
|
+
setMessages((prev) => upsertTrailingCompaction(prev, segments));
|
|
50959
|
+
return;
|
|
50960
|
+
}
|
|
50961
|
+
if (meta?.append) {
|
|
50962
|
+
setMessages((prev) => appendToTrailingAssistant(prev, segments));
|
|
50963
|
+
return;
|
|
50964
|
+
}
|
|
50683
50965
|
setMessages((prev) => updateTrailingAssistant(prev, segments));
|
|
50684
50966
|
},
|
|
50685
|
-
onStreamStart: () =>
|
|
50967
|
+
onStreamStart: () => {
|
|
50968
|
+
setStreamingPhase("streaming");
|
|
50969
|
+
const adoptTail = adoptTrailingAssistantRef.current;
|
|
50970
|
+
adoptTrailingAssistantRef.current = false;
|
|
50971
|
+
setMessages((prev) => {
|
|
50972
|
+
const last = prev[prev.length - 1];
|
|
50973
|
+
if (!last || last.role !== "assistant" || adoptTail) return prev;
|
|
50974
|
+
const hasContent = (last.segments?.length ?? 0) > 0 || last.content !== "";
|
|
50975
|
+
if (!hasContent) return prev;
|
|
50976
|
+
return [
|
|
50977
|
+
...prev,
|
|
50978
|
+
{ id: nextId("assistant"), role: "assistant", content: "", segments: [] }
|
|
50979
|
+
];
|
|
50980
|
+
});
|
|
50981
|
+
},
|
|
50686
50982
|
onStreamEnd: () => setStreamingPhase("idle"),
|
|
50687
50983
|
// Agent is executing (approved) commands outside an open stream — keep
|
|
50688
50984
|
// the composer locked exactly like the in-stream phases. An open stream
|
|
50689
50985
|
// keeps ownership: only 'idle' upgrades to 'thinking'. Suppressed during
|
|
50690
50986
|
// initial catchup so a replayed dead tail can't lock a finished dialog.
|
|
50691
50987
|
onAgentBusy: () => {
|
|
50692
|
-
if (suppressAgentBusyRef.current) return;
|
|
50988
|
+
if (suppressAgentBusyRef.current > 0) return;
|
|
50693
50989
|
setStreamingPhase((p) => p === "idle" ? "thinking" : p);
|
|
50694
50990
|
},
|
|
50695
50991
|
// Terminal turn failures can arrive without a MESSAGE_END; unlock the
|
|
@@ -50704,27 +51000,171 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50704
51000
|
provider: meta.providerName || null,
|
|
50705
51001
|
modelLabel: meta.modelDisplayName || meta.modelName || null,
|
|
50706
51002
|
contextWindowMaxTokens: meta.contextWindow || null
|
|
50707
|
-
})
|
|
51003
|
+
}),
|
|
51004
|
+
// Post-MESSAGE_END tool chunks (approved commands executing after the
|
|
51005
|
+
// approval bubble, async batch results). Routed through the cross-message
|
|
51006
|
+
// updater — the accumulator was reset at MESSAGE_END, so the old
|
|
51007
|
+
// fallthrough replaced the whole trailing bubble with one tool segment.
|
|
51008
|
+
onToolExecuted: (segment) => {
|
|
51009
|
+
setMessages((prev) => applyToolExecutionToMessages(prev, segment));
|
|
51010
|
+
},
|
|
51011
|
+
// Cross-message approval status flip. Wiring this also makes the
|
|
51012
|
+
// processor skip its cumulative re-emit for resolved approvals — which,
|
|
51013
|
+
// post-MESSAGE_END, was an empty array that blanked the trailing bubble.
|
|
51014
|
+
onApprovalResolved: (requestId, status, _approvalType, resolvedByName) => {
|
|
51015
|
+
setMessages((prev) => {
|
|
51016
|
+
let changed = false;
|
|
51017
|
+
const next = prev.map((m) => {
|
|
51018
|
+
if (m.role !== "assistant" || !m.segments) return m;
|
|
51019
|
+
let msgChanged = false;
|
|
51020
|
+
const segs = m.segments.map((s) => {
|
|
51021
|
+
if (s.type === "approval_request" && s.data.requestId === requestId && s.status !== status) {
|
|
51022
|
+
msgChanged = true;
|
|
51023
|
+
return { ...s, status };
|
|
51024
|
+
}
|
|
51025
|
+
if (s.type === "approval_batch" && s.data.approvalRequestId === requestId) {
|
|
51026
|
+
const nextResolvedBy = resolvedByName ?? s.resolvedByName;
|
|
51027
|
+
if (s.status === status && nextResolvedBy === s.resolvedByName) return s;
|
|
51028
|
+
msgChanged = true;
|
|
51029
|
+
return { ...s, status, resolvedByName: nextResolvedBy };
|
|
51030
|
+
}
|
|
51031
|
+
return s;
|
|
51032
|
+
});
|
|
51033
|
+
if (!msgChanged) return m;
|
|
51034
|
+
changed = true;
|
|
51035
|
+
return { ...m, segments: segs };
|
|
51036
|
+
});
|
|
51037
|
+
return changed ? next : prev;
|
|
51038
|
+
});
|
|
51039
|
+
setApprovalStatuses(
|
|
51040
|
+
(prev) => prev[requestId] === status ? prev : { ...prev, [requestId]: status }
|
|
51041
|
+
);
|
|
51042
|
+
},
|
|
51043
|
+
// MESSAGE_REQUEST echo — a user message from THIS or another session.
|
|
51044
|
+
onUserMessage: (text, meta) => {
|
|
51045
|
+
if (!text) return;
|
|
51046
|
+
const seq = meta?.streamSeq;
|
|
51047
|
+
if (typeof seq === "number") {
|
|
51048
|
+
if (seenParticipantSeqsRef.current.has(seq)) return;
|
|
51049
|
+
seenParticipantSeqsRef.current.add(seq);
|
|
51050
|
+
}
|
|
51051
|
+
if (meta?.ownerType !== "ADMIN") {
|
|
51052
|
+
const echoIdx = pendingEchoTextsRef.current.indexOf(text);
|
|
51053
|
+
if (echoIdx !== -1) {
|
|
51054
|
+
pendingEchoTextsRef.current.splice(echoIdx, 1);
|
|
51055
|
+
return;
|
|
51056
|
+
}
|
|
51057
|
+
}
|
|
51058
|
+
const authorType = meta?.ownerType === "ADMIN" ? "admin" : "user";
|
|
51059
|
+
setMessages((prev) => {
|
|
51060
|
+
if (typeof seq !== "number" && hasRecentMessage(
|
|
51061
|
+
prev,
|
|
51062
|
+
(m) => m.role === "user" && (m.authorType ?? "user") === authorType && m.content === text,
|
|
51063
|
+
CONTENT_DEDUP_WINDOW
|
|
51064
|
+
)) {
|
|
51065
|
+
return prev;
|
|
51066
|
+
}
|
|
51067
|
+
return [
|
|
51068
|
+
...prev,
|
|
51069
|
+
{
|
|
51070
|
+
id: nextId("user"),
|
|
51071
|
+
role: "user",
|
|
51072
|
+
content: text,
|
|
51073
|
+
...meta?.displayName ? { name: meta.displayName } : {},
|
|
51074
|
+
authorType,
|
|
51075
|
+
...meta?.contextItems && meta.contextItems.length > 0 ? {
|
|
51076
|
+
contextItems: meta.contextItems.map((ci) => ({
|
|
51077
|
+
type: ci.type,
|
|
51078
|
+
id: ci.id,
|
|
51079
|
+
label: ci.label ?? ci.id
|
|
51080
|
+
}))
|
|
51081
|
+
} : {}
|
|
51082
|
+
}
|
|
51083
|
+
];
|
|
51084
|
+
});
|
|
51085
|
+
},
|
|
51086
|
+
// Technician / admin direct message into the dialog.
|
|
51087
|
+
onDirectMessage: (text, meta) => {
|
|
51088
|
+
if (!text) return;
|
|
51089
|
+
const seq = meta?.streamSeq;
|
|
51090
|
+
if (typeof seq === "number") {
|
|
51091
|
+
if (seenParticipantSeqsRef.current.has(seq)) return;
|
|
51092
|
+
seenParticipantSeqsRef.current.add(seq);
|
|
51093
|
+
}
|
|
51094
|
+
setMessages((prev) => {
|
|
51095
|
+
if (typeof seq !== "number" && hasRecentMessage(
|
|
51096
|
+
prev,
|
|
51097
|
+
(m) => m.role === "user" && m.authorType === "admin" && m.content === text,
|
|
51098
|
+
CONTENT_DEDUP_WINDOW
|
|
51099
|
+
)) {
|
|
51100
|
+
return prev;
|
|
51101
|
+
}
|
|
51102
|
+
return [
|
|
51103
|
+
...prev,
|
|
51104
|
+
{
|
|
51105
|
+
id: `direct-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
51106
|
+
role: "user",
|
|
51107
|
+
content: text,
|
|
51108
|
+
name: meta?.displayName ?? "Admin",
|
|
51109
|
+
authorType: "admin"
|
|
51110
|
+
}
|
|
51111
|
+
];
|
|
51112
|
+
});
|
|
51113
|
+
},
|
|
51114
|
+
// System notice — rendered as a name-only row (same shape the history
|
|
51115
|
+
// processor produces via `pushStandaloneMessages`).
|
|
51116
|
+
onSystemMessage: (text, meta) => {
|
|
51117
|
+
if (!text) return;
|
|
51118
|
+
const seq = meta?.streamSeq;
|
|
51119
|
+
if (typeof seq === "number") {
|
|
51120
|
+
if (seenParticipantSeqsRef.current.has(seq)) return;
|
|
51121
|
+
seenParticipantSeqsRef.current.add(seq);
|
|
51122
|
+
}
|
|
51123
|
+
setMessages((prev) => {
|
|
51124
|
+
if (typeof seq !== "number" && hasRecentMessage(prev, (m) => m.authorType === "system" && m.name === text, SYSTEM_DEDUP_WINDOW)) {
|
|
51125
|
+
return prev;
|
|
51126
|
+
}
|
|
51127
|
+
return [
|
|
51128
|
+
...prev,
|
|
51129
|
+
{
|
|
51130
|
+
id: `system-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
51131
|
+
role: "user",
|
|
51132
|
+
content: "",
|
|
51133
|
+
name: text,
|
|
51134
|
+
authorType: "system"
|
|
51135
|
+
}
|
|
51136
|
+
];
|
|
51137
|
+
});
|
|
51138
|
+
}
|
|
50708
51139
|
});
|
|
50709
51140
|
const { processChunk, reset: resetAccumulator } = useRealtimeChunkProcessor({
|
|
50710
51141
|
callbacks: {
|
|
50711
|
-
onSegmentsUpdate: (segments) => callbacksRef.current.onSegmentsUpdate(segments),
|
|
51142
|
+
onSegmentsUpdate: (segments, meta) => callbacksRef.current.onSegmentsUpdate(segments, meta),
|
|
50712
51143
|
onStreamStart: () => callbacksRef.current.onStreamStart(),
|
|
50713
51144
|
onStreamEnd: () => callbacksRef.current.onStreamEnd(),
|
|
50714
51145
|
onAgentBusy: () => callbacksRef.current.onAgentBusy(),
|
|
50715
51146
|
onError: () => callbacksRef.current.onError(),
|
|
50716
51147
|
onTokenUsage: (data) => callbacksRef.current.onTokenUsage(data),
|
|
50717
51148
|
onMetadata: (meta) => callbacksRef.current.onMetadata(meta),
|
|
51149
|
+
onToolExecuted: (segment) => callbacksRef.current.onToolExecuted(segment),
|
|
51150
|
+
onApprovalResolved: (requestId, status, approvalType, resolvedByName) => callbacksRef.current.onApprovalResolved(requestId, status, approvalType, resolvedByName),
|
|
51151
|
+
onUserMessage: (text, meta) => callbacksRef.current.onUserMessage(text, meta),
|
|
51152
|
+
onDirectMessage: (text, meta) => callbacksRef.current.onDirectMessage(text, meta),
|
|
51153
|
+
onSystemMessage: (text, meta) => callbacksRef.current.onSystemMessage(text, meta),
|
|
50718
51154
|
onApprove: accumApprove,
|
|
50719
51155
|
onReject: accumReject
|
|
50720
51156
|
},
|
|
50721
|
-
batchApprovalsEnabled
|
|
51157
|
+
batchApprovalsEnabled,
|
|
51158
|
+
approvalStatuses,
|
|
51159
|
+
...displayApprovalTypes ? { displayApprovalTypes } : {}
|
|
50722
51160
|
});
|
|
50723
51161
|
const {
|
|
50724
51162
|
processChunk: catchupProcessChunk,
|
|
50725
51163
|
catchUpChunks,
|
|
50726
51164
|
startInitialBuffering,
|
|
50727
|
-
resetChunkTracking
|
|
51165
|
+
resetChunkTracking,
|
|
51166
|
+
resetAndCatchUp,
|
|
51167
|
+
isBufferingActive
|
|
50728
51168
|
} = useChunkCatchup({
|
|
50729
51169
|
dialogId: active ? dialogId : null,
|
|
50730
51170
|
onChunkReceived: (chunk) => processChunk(chunk),
|
|
@@ -50753,11 +51193,13 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50753
51193
|
onApprove: accumApprove,
|
|
50754
51194
|
onReject: accumReject,
|
|
50755
51195
|
approvalStatuses,
|
|
50756
|
-
batchApprovalsEnabled
|
|
51196
|
+
batchApprovalsEnabled,
|
|
51197
|
+
...displayApprovalTypes ? { displayApprovalTypes } : {}
|
|
50757
51198
|
}
|
|
50758
51199
|
);
|
|
50759
51200
|
const unified = mapProcessedToUnified(rawProcessed);
|
|
50760
51201
|
if (cursor === void 0) {
|
|
51202
|
+
adoptTrailingAssistantRef.current = isBufferingActive() && extractIncompleteMessageState(rawProcessed[rawProcessed.length - 1]) !== void 0;
|
|
50761
51203
|
setMessages(unified);
|
|
50762
51204
|
} else {
|
|
50763
51205
|
setMessages((prev) => [...unified, ...prev]);
|
|
@@ -50781,8 +51223,10 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50781
51223
|
chatTypeFilter,
|
|
50782
51224
|
approvalStatuses,
|
|
50783
51225
|
batchApprovalsEnabled,
|
|
51226
|
+
displayApprovalTypes,
|
|
50784
51227
|
accumApprove,
|
|
50785
|
-
accumReject
|
|
51228
|
+
accumReject,
|
|
51229
|
+
isBufferingActive
|
|
50786
51230
|
]
|
|
50787
51231
|
);
|
|
50788
51232
|
const prevDialogIdRef = useRef74(void 0);
|
|
@@ -50791,6 +51235,9 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50791
51235
|
prevDialogIdRef.current = dialogId;
|
|
50792
51236
|
historyLoadSeqRef.current += 1;
|
|
50793
51237
|
resetAccumulator();
|
|
51238
|
+
adoptTrailingAssistantRef.current = false;
|
|
51239
|
+
seenParticipantSeqsRef.current.clear();
|
|
51240
|
+
pendingEchoTextsRef.current = [];
|
|
50794
51241
|
setMessages([]);
|
|
50795
51242
|
setMessagesNextCursor(null);
|
|
50796
51243
|
setDialogTokenUsage(null);
|
|
@@ -50802,13 +51249,16 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50802
51249
|
}, [active, dialogId, loadDialogHistory, resetAccumulator]);
|
|
50803
51250
|
useEffect88(() => {
|
|
50804
51251
|
if (!active || !dialogId) return;
|
|
50805
|
-
suppressAgentBusyRef.current
|
|
51252
|
+
suppressAgentBusyRef.current += 1;
|
|
50806
51253
|
resetChunkTracking();
|
|
50807
51254
|
startInitialBuffering();
|
|
50808
51255
|
catchUpChunks().catch((err) => {
|
|
50809
51256
|
console.error("[useNatsChatAdapter] initial catchup failed:", err);
|
|
50810
51257
|
}).finally(() => {
|
|
50811
|
-
suppressAgentBusyRef.current =
|
|
51258
|
+
suppressAgentBusyRef.current = Math.max(0, suppressAgentBusyRef.current - 1);
|
|
51259
|
+
if (dialogId === currentDialogIdRef.current) {
|
|
51260
|
+
adoptTrailingAssistantRef.current = false;
|
|
51261
|
+
}
|
|
50812
51262
|
});
|
|
50813
51263
|
}, [active, dialogId, resetChunkTracking, startInitialBuffering, catchUpChunks]);
|
|
50814
51264
|
useNatsDialogSubscription({
|
|
@@ -50823,6 +51273,30 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50823
51273
|
onEvent: (payload, messageType) => {
|
|
50824
51274
|
catchupProcessChunk(payload, messageType);
|
|
50825
51275
|
setConnectionState("connected");
|
|
51276
|
+
},
|
|
51277
|
+
onConnect: () => {
|
|
51278
|
+
if (!hasConnectedOnceRef.current) {
|
|
51279
|
+
hasConnectedOnceRef.current = true;
|
|
51280
|
+
return;
|
|
51281
|
+
}
|
|
51282
|
+
suppressAgentBusyRef.current += 1;
|
|
51283
|
+
startInitialBuffering();
|
|
51284
|
+
void (async () => {
|
|
51285
|
+
try {
|
|
51286
|
+
if (dialogId && fetchDialogMessages) {
|
|
51287
|
+
await loadDialogHistory(dialogId);
|
|
51288
|
+
}
|
|
51289
|
+
if (dialogId !== currentDialogIdRef.current) return;
|
|
51290
|
+
await resetAndCatchUp();
|
|
51291
|
+
} catch (err) {
|
|
51292
|
+
console.error("[useNatsChatAdapter] reconnect catchup failed:", err);
|
|
51293
|
+
} finally {
|
|
51294
|
+
suppressAgentBusyRef.current = Math.max(0, suppressAgentBusyRef.current - 1);
|
|
51295
|
+
if (dialogId === currentDialogIdRef.current) {
|
|
51296
|
+
adoptTrailingAssistantRef.current = false;
|
|
51297
|
+
}
|
|
51298
|
+
}
|
|
51299
|
+
})();
|
|
50826
51300
|
}
|
|
50827
51301
|
});
|
|
50828
51302
|
useEffect88(() => {
|
|
@@ -50874,6 +51348,8 @@ function useNatsChatAdapter(config, options = {}) {
|
|
|
50874
51348
|
const sendMessage = useCallback53(
|
|
50875
51349
|
async (text, sendOptions) => {
|
|
50876
51350
|
const hidden = sendOptions?.hidden ?? false;
|
|
51351
|
+
pendingEchoTextsRef.current.push(text);
|
|
51352
|
+
if (pendingEchoTextsRef.current.length > 5) pendingEchoTextsRef.current.shift();
|
|
50877
51353
|
setMessages((prev) => [
|
|
50878
51354
|
...prev,
|
|
50879
51355
|
{
|
|
@@ -51254,65 +51730,6 @@ function useUnifiedChat(options) {
|
|
|
51254
51730
|
);
|
|
51255
51731
|
}
|
|
51256
51732
|
|
|
51257
|
-
// src/components/chat/utils/extract-incomplete-message-state.ts
|
|
51258
|
-
function extractIncompleteMessageState(lastMessage) {
|
|
51259
|
-
if (!lastMessage || lastMessage.role !== "assistant" || typeof lastMessage.content === "string") {
|
|
51260
|
-
return void 0;
|
|
51261
|
-
}
|
|
51262
|
-
const segments = lastMessage.content;
|
|
51263
|
-
const pendingApprovals = /* @__PURE__ */ new Map();
|
|
51264
|
-
const executingTools = /* @__PURE__ */ new Map();
|
|
51265
|
-
let hasIncompleteState = false;
|
|
51266
|
-
segments.forEach((segment) => {
|
|
51267
|
-
switch (segment.type) {
|
|
51268
|
-
case "tool_execution":
|
|
51269
|
-
if (segment.data.type === "EXECUTING_TOOL") {
|
|
51270
|
-
const toolKey = segment.data.toolExecutionRequestId || `${segment.data.integratedToolType}-${segment.data.toolFunction}`;
|
|
51271
|
-
executingTools.set(toolKey, {
|
|
51272
|
-
integratedToolType: segment.data.integratedToolType,
|
|
51273
|
-
toolFunction: segment.data.toolFunction,
|
|
51274
|
-
toolTitle: segment.data.toolTitle,
|
|
51275
|
-
parameters: segment.data.parameters
|
|
51276
|
-
});
|
|
51277
|
-
hasIncompleteState = true;
|
|
51278
|
-
}
|
|
51279
|
-
break;
|
|
51280
|
-
case "approval_request":
|
|
51281
|
-
if (segment.status === "pending" && segment.data.requestId) {
|
|
51282
|
-
pendingApprovals.set(segment.data.requestId, {
|
|
51283
|
-
command: segment.data.command,
|
|
51284
|
-
explanation: segment.data.explanation,
|
|
51285
|
-
approvalType: segment.data.approvalType || "CLIENT"
|
|
51286
|
-
});
|
|
51287
|
-
hasIncompleteState = true;
|
|
51288
|
-
}
|
|
51289
|
-
break;
|
|
51290
|
-
case "approval_batch": {
|
|
51291
|
-
const allDone = !!segment.data.executions && segment.data.toolCalls.every(
|
|
51292
|
-
(c) => segment.data.executions?.[c.toolExecutionRequestId]?.status === "done"
|
|
51293
|
-
);
|
|
51294
|
-
if (segment.status !== "rejected" && !allDone) {
|
|
51295
|
-
hasIncompleteState = true;
|
|
51296
|
-
}
|
|
51297
|
-
break;
|
|
51298
|
-
}
|
|
51299
|
-
case "context_compaction":
|
|
51300
|
-
if (segment.status === "started") {
|
|
51301
|
-
hasIncompleteState = true;
|
|
51302
|
-
}
|
|
51303
|
-
break;
|
|
51304
|
-
}
|
|
51305
|
-
});
|
|
51306
|
-
if (!hasIncompleteState) {
|
|
51307
|
-
return void 0;
|
|
51308
|
-
}
|
|
51309
|
-
return {
|
|
51310
|
-
existingSegments: segments,
|
|
51311
|
-
pendingApprovals: pendingApprovals.size > 0 ? pendingApprovals : void 0,
|
|
51312
|
-
executingTools: executingTools.size > 0 ? executingTools : void 0
|
|
51313
|
-
};
|
|
51314
|
-
}
|
|
51315
|
-
|
|
51316
51733
|
// src/components/chat/utils/history-merge.ts
|
|
51317
51734
|
var SYNTHETIC_REALTIME_ID_PREFIXES = ["assistant-", "user-", "direct-", "system-", "error-"];
|
|
51318
51735
|
function isSyntheticRealtimeId(id) {
|
|
@@ -53697,11 +54114,14 @@ export {
|
|
|
53697
54114
|
processHistoricalMessages,
|
|
53698
54115
|
extractErrorMessages,
|
|
53699
54116
|
processHistoricalMessagesWithErrors,
|
|
54117
|
+
extractIncompleteMessageState,
|
|
54118
|
+
appendToTrailingAssistant,
|
|
54119
|
+
upsertTrailingCompaction,
|
|
54120
|
+
applyToolExecutionToMessages,
|
|
53700
54121
|
mapProcessedToUnified,
|
|
53701
54122
|
historicalToUnified,
|
|
53702
54123
|
useNatsChatAdapter,
|
|
53703
54124
|
useUnifiedChat,
|
|
53704
|
-
extractIncompleteMessageState,
|
|
53705
54125
|
SYNTHETIC_REALTIME_ID_PREFIXES,
|
|
53706
54126
|
flattenMessagePagesChronological,
|
|
53707
54127
|
maxPersistedStreamSeq,
|
|
@@ -54118,4 +54538,4 @@ export {
|
|
|
54118
54538
|
LogsList,
|
|
54119
54539
|
assets
|
|
54120
54540
|
};
|
|
54121
|
-
//# sourceMappingURL=chunk-
|
|
54541
|
+
//# sourceMappingURL=chunk-3BHV2QAH.js.map
|