@yushaw/sanqian-chat 0.2.37 → 0.2.40
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/renderer/index.d.mts +89 -11
- package/dist/renderer/index.d.ts +89 -11
- package/dist/renderer/index.js +240 -36
- package/dist/renderer/index.mjs +240 -36
- package/package.json +1 -1
- package/src/renderer/styles/chat.css +34 -8
- package/src/renderer/styles/coreCss.ts +34 -8
- package/src/renderer/styles/safe.css +34 -8
package/dist/renderer/index.js
CHANGED
|
@@ -107,6 +107,12 @@ var findLastBlock = (blocks, predicate) => {
|
|
|
107
107
|
}
|
|
108
108
|
return void 0;
|
|
109
109
|
};
|
|
110
|
+
var CHAT_CAPABILITIES = {
|
|
111
|
+
conversationSwitch: {
|
|
112
|
+
supportsCancelActiveStream: true,
|
|
113
|
+
supportsDetachContext: true
|
|
114
|
+
}
|
|
115
|
+
};
|
|
110
116
|
function useChat(options) {
|
|
111
117
|
const { adapter, onError, onConversationChange } = options;
|
|
112
118
|
const [messages, setMessages] = (0, import_react.useState)([]);
|
|
@@ -127,6 +133,7 @@ function useChat(options) {
|
|
|
127
133
|
const pendingCancelRef = (0, import_react.useRef)(false);
|
|
128
134
|
const pendingCancelFnRef = (0, import_react.useRef)(null);
|
|
129
135
|
const suppressStreamRef = (0, import_react.useRef)(false);
|
|
136
|
+
const activeStreamContextRef = (0, import_react.useRef)(null);
|
|
130
137
|
const currentBlocksRef = (0, import_react.useRef)([]);
|
|
131
138
|
const currentTextBlockIndexRef = (0, import_react.useRef)(-1);
|
|
132
139
|
const needsContentClearRef = (0, import_react.useRef)(false);
|
|
@@ -214,8 +221,43 @@ function useChat(options) {
|
|
|
214
221
|
pendingCancelRef.current = false;
|
|
215
222
|
pendingCancelFnRef.current = null;
|
|
216
223
|
}, []);
|
|
217
|
-
const
|
|
224
|
+
const detachActiveStream = (0, import_react.useCallback)((detachContext) => {
|
|
225
|
+
const context = activeStreamContextRef.current;
|
|
226
|
+
if (!context || context.detached) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
context.detached = true;
|
|
230
|
+
context.detachContext = detachContext;
|
|
231
|
+
if (typewriterIntervalRef.current) {
|
|
232
|
+
clearTimeout(typewriterIntervalRef.current);
|
|
233
|
+
typewriterIntervalRef.current = null;
|
|
234
|
+
}
|
|
235
|
+
currentAssistantMessageIdRef.current = null;
|
|
236
|
+
resetStreamBuffers();
|
|
237
|
+
setIsStreaming(false);
|
|
238
|
+
setIsLoading(false);
|
|
239
|
+
setPendingInterrupt(null);
|
|
240
|
+
currentRunIdRef.current = null;
|
|
241
|
+
pendingInterruptStreamIdRef.current = null;
|
|
242
|
+
clearPendingCancel();
|
|
243
|
+
suppressStreamRef.current = false;
|
|
244
|
+
}, [clearPendingCancel, resetStreamBuffers]);
|
|
245
|
+
const handleStreamEvent = (0, import_react.useCallback)((event, streamContext) => {
|
|
218
246
|
if (!isMountedRef.current) return;
|
|
247
|
+
const isActiveStream = activeStreamContextRef.current?.token === streamContext.token && !streamContext.detached;
|
|
248
|
+
if (!isActiveStream) {
|
|
249
|
+
if (event.type === "done" && event.conversationId && !streamContext.didReportConversationChange) {
|
|
250
|
+
streamContext.didReportConversationChange = true;
|
|
251
|
+
onConversationChange?.(event.conversationId, event.title, {
|
|
252
|
+
source: "background",
|
|
253
|
+
streamToken: streamContext.token,
|
|
254
|
+
detached: true,
|
|
255
|
+
detachContext: streamContext.detachContext
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const assistantMessageId = streamContext.assistantMessageId;
|
|
219
261
|
currentAssistantMessageIdRef.current = assistantMessageId;
|
|
220
262
|
if (suppressStreamRef.current && event.type !== "start" && event.type !== "cancelled" && event.type !== "done" && event.type !== "error") {
|
|
221
263
|
return;
|
|
@@ -561,8 +603,13 @@ function useChat(options) {
|
|
|
561
603
|
});
|
|
562
604
|
resetStreamBuffers();
|
|
563
605
|
if (event.conversationId) {
|
|
606
|
+
streamContext.didReportConversationChange = true;
|
|
564
607
|
setConversationId(event.conversationId);
|
|
565
|
-
onConversationChange?.(event.conversationId, event.title
|
|
608
|
+
onConversationChange?.(event.conversationId, event.title, {
|
|
609
|
+
source: "active",
|
|
610
|
+
streamToken: streamContext.token,
|
|
611
|
+
detached: false
|
|
612
|
+
});
|
|
566
613
|
}
|
|
567
614
|
if (event.title) setConversationTitle(event.title);
|
|
568
615
|
setIsStreaming(false);
|
|
@@ -571,6 +618,7 @@ function useChat(options) {
|
|
|
571
618
|
pendingInterruptStreamIdRef.current = null;
|
|
572
619
|
suppressStreamRef.current = false;
|
|
573
620
|
clearPendingCancel();
|
|
621
|
+
activeStreamContextRef.current = null;
|
|
574
622
|
break;
|
|
575
623
|
}
|
|
576
624
|
case "cancelled": {
|
|
@@ -608,6 +656,7 @@ function useChat(options) {
|
|
|
608
656
|
pendingInterruptStreamIdRef.current = null;
|
|
609
657
|
suppressStreamRef.current = false;
|
|
610
658
|
clearPendingCancel();
|
|
659
|
+
activeStreamContextRef.current = null;
|
|
611
660
|
break;
|
|
612
661
|
}
|
|
613
662
|
case "error": {
|
|
@@ -636,6 +685,7 @@ function useChat(options) {
|
|
|
636
685
|
pendingInterruptStreamIdRef.current = null;
|
|
637
686
|
suppressStreamRef.current = false;
|
|
638
687
|
clearPendingCancel();
|
|
688
|
+
activeStreamContextRef.current = null;
|
|
639
689
|
break;
|
|
640
690
|
}
|
|
641
691
|
case "interrupt": {
|
|
@@ -686,6 +736,13 @@ function useChat(options) {
|
|
|
686
736
|
blocks: [],
|
|
687
737
|
isComplete: false
|
|
688
738
|
};
|
|
739
|
+
const streamContext = {
|
|
740
|
+
token: crypto.randomUUID(),
|
|
741
|
+
assistantMessageId: assistantMessage.id,
|
|
742
|
+
detached: false,
|
|
743
|
+
didReportConversationChange: false
|
|
744
|
+
};
|
|
745
|
+
activeStreamContextRef.current = streamContext;
|
|
689
746
|
const shouldRenderUserMessage = trimmedContent.length > 0 || hasAttachedResources;
|
|
690
747
|
setMessages(
|
|
691
748
|
(prev) => shouldRenderUserMessage ? [...prev, userMessage, assistantMessage] : [...prev, assistantMessage]
|
|
@@ -708,7 +765,7 @@ function useChat(options) {
|
|
|
708
765
|
const { cancel } = await adapter.chatStream(
|
|
709
766
|
apiMessages,
|
|
710
767
|
conversationIdRef.current ?? void 0,
|
|
711
|
-
(event) => handleStreamEvent(event,
|
|
768
|
+
(event) => handleStreamEvent(event, streamContext),
|
|
712
769
|
{
|
|
713
770
|
agentId: currentAgentIdRef.current,
|
|
714
771
|
attachedResources: attachedResources?.length ? attachedResources : void 0,
|
|
@@ -743,6 +800,9 @@ function useChat(options) {
|
|
|
743
800
|
pendingInterruptStreamIdRef.current = null;
|
|
744
801
|
setIsLoading(false);
|
|
745
802
|
setIsStreaming(false);
|
|
803
|
+
if (activeStreamContextRef.current?.token === streamContext.token) {
|
|
804
|
+
activeStreamContextRef.current = null;
|
|
805
|
+
}
|
|
746
806
|
return false;
|
|
747
807
|
}
|
|
748
808
|
}, [adapter, clearPendingCancel, handleStreamEvent, onError, resetStreamBuffers, sessionResources]);
|
|
@@ -784,6 +844,7 @@ function useChat(options) {
|
|
|
784
844
|
resetStreamBuffers();
|
|
785
845
|
currentRunIdRef.current = null;
|
|
786
846
|
pendingInterruptStreamIdRef.current = null;
|
|
847
|
+
activeStreamContextRef.current = null;
|
|
787
848
|
setIsStreaming(false);
|
|
788
849
|
setIsLoading(false);
|
|
789
850
|
}, [clearPendingCancel, flushTypewriter, resetStreamBuffers]);
|
|
@@ -797,10 +858,20 @@ function useChat(options) {
|
|
|
797
858
|
resetStreamBuffers();
|
|
798
859
|
currentRunIdRef.current = null;
|
|
799
860
|
pendingInterruptStreamIdRef.current = null;
|
|
861
|
+
activeStreamContextRef.current = null;
|
|
800
862
|
clearPendingCancel();
|
|
801
863
|
suppressStreamRef.current = false;
|
|
802
864
|
}, [clearPendingCancel, resetStreamBuffers]);
|
|
803
|
-
const loadConversation = (0, import_react.useCallback)(async (id) => {
|
|
865
|
+
const loadConversation = (0, import_react.useCallback)(async (id, optionsArg) => {
|
|
866
|
+
const cancelActiveStream = optionsArg?.cancelActiveStream ?? true;
|
|
867
|
+
const activeStream = activeStreamContextRef.current;
|
|
868
|
+
if (activeStream && !activeStream.detached) {
|
|
869
|
+
if (cancelActiveStream) {
|
|
870
|
+
stopStreaming();
|
|
871
|
+
} else {
|
|
872
|
+
detachActiveStream(optionsArg?.detachContext);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
804
875
|
try {
|
|
805
876
|
setIsLoading(true);
|
|
806
877
|
setError(null);
|
|
@@ -821,9 +892,19 @@ function useChat(options) {
|
|
|
821
892
|
} finally {
|
|
822
893
|
if (isMountedRef.current) setIsLoading(false);
|
|
823
894
|
}
|
|
824
|
-
}, [adapter, onError]);
|
|
825
|
-
const newConversation = (0, import_react.useCallback)(() => {
|
|
826
|
-
|
|
895
|
+
}, [adapter, detachActiveStream, onError, stopStreaming]);
|
|
896
|
+
const newConversation = (0, import_react.useCallback)((optionsArg) => {
|
|
897
|
+
const cancelActiveStream = optionsArg?.cancelActiveStream ?? true;
|
|
898
|
+
const activeStream = activeStreamContextRef.current;
|
|
899
|
+
if (activeStream && !activeStream.detached) {
|
|
900
|
+
if (cancelActiveStream) {
|
|
901
|
+
stopStreaming();
|
|
902
|
+
} else {
|
|
903
|
+
detachActiveStream(optionsArg?.detachContext);
|
|
904
|
+
}
|
|
905
|
+
} else if (cancelActiveStream) {
|
|
906
|
+
cancelRef.current?.();
|
|
907
|
+
}
|
|
827
908
|
if (typewriterIntervalRef.current) clearTimeout(typewriterIntervalRef.current);
|
|
828
909
|
setMessages([]);
|
|
829
910
|
setConversationId(null);
|
|
@@ -835,8 +916,9 @@ function useChat(options) {
|
|
|
835
916
|
resetStreamBuffers();
|
|
836
917
|
currentRunIdRef.current = null;
|
|
837
918
|
pendingInterruptStreamIdRef.current = null;
|
|
919
|
+
activeStreamContextRef.current = null;
|
|
838
920
|
clearPendingCancel();
|
|
839
|
-
}, [clearPendingCancel, resetStreamBuffers]);
|
|
921
|
+
}, [clearPendingCancel, detachActiveStream, resetStreamBuffers, stopStreaming]);
|
|
840
922
|
const sendHitlResponse = (0, import_react.useCallback)((response) => {
|
|
841
923
|
const runId = currentRunIdRef.current ?? void 0;
|
|
842
924
|
const streamId = pendingInterruptStreamIdRef.current ?? void 0;
|
|
@@ -916,7 +998,8 @@ function useChat(options) {
|
|
|
916
998
|
loadConversation,
|
|
917
999
|
newConversation,
|
|
918
1000
|
sessionResources,
|
|
919
|
-
removeSessionResource
|
|
1001
|
+
removeSessionResource,
|
|
1002
|
+
capabilities: CHAT_CAPABILITIES
|
|
920
1003
|
};
|
|
921
1004
|
}
|
|
922
1005
|
|
|
@@ -1837,33 +1920,56 @@ code {
|
|
|
1837
1920
|
|
|
1838
1921
|
[data-streamdown="code-block-header"] {
|
|
1839
1922
|
position: absolute !important;
|
|
1840
|
-
top:
|
|
1841
|
-
|
|
1923
|
+
top: 10px !important;
|
|
1924
|
+
left: 12px !important;
|
|
1925
|
+
right: auto !important;
|
|
1842
1926
|
z-index: 10;
|
|
1843
1927
|
padding: 0 !important;
|
|
1844
1928
|
background: transparent !important;
|
|
1845
1929
|
border: none !important;
|
|
1846
1930
|
opacity: 0;
|
|
1847
1931
|
transition: opacity 150ms ease;
|
|
1932
|
+
pointer-events: none;
|
|
1848
1933
|
}
|
|
1849
1934
|
|
|
1850
|
-
[data-streamdown="code-block
|
|
1935
|
+
[data-streamdown="code-block-actions"] {
|
|
1936
|
+
position: absolute !important;
|
|
1937
|
+
top: 10px !important;
|
|
1938
|
+
right: 8px !important;
|
|
1939
|
+
z-index: 11;
|
|
1940
|
+
display: flex !important;
|
|
1941
|
+
align-items: center;
|
|
1942
|
+
gap: 4px;
|
|
1943
|
+
padding: 0 !important;
|
|
1944
|
+
background: transparent !important;
|
|
1945
|
+
border: none !important;
|
|
1946
|
+
opacity: 0;
|
|
1947
|
+
transition: opacity 150ms ease;
|
|
1948
|
+
pointer-events: auto !important;
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
[data-streamdown="code-block"]:hover [data-streamdown="code-block-header"],
|
|
1952
|
+
[data-streamdown="code-block"]:hover [data-streamdown="code-block-actions"] {
|
|
1851
1953
|
opacity: 1;
|
|
1852
1954
|
}
|
|
1853
1955
|
|
|
1854
1956
|
[data-streamdown="code-block-header"] > span:first-child {
|
|
1957
|
+
display: inline-flex;
|
|
1855
1958
|
font-size: 11px;
|
|
1856
1959
|
color: var(--color-muted);
|
|
1857
1960
|
text-transform: lowercase;
|
|
1858
|
-
margin-right: 8px;
|
|
1859
1961
|
}
|
|
1860
1962
|
|
|
1861
1963
|
[data-streamdown="code-block-header"] > div {
|
|
1862
1964
|
display: flex;
|
|
1863
1965
|
gap: 4px;
|
|
1966
|
+
margin-left: 8px;
|
|
1967
|
+
pointer-events: auto;
|
|
1864
1968
|
}
|
|
1865
1969
|
|
|
1866
|
-
|
|
1970
|
+
/* Normalize action buttons for both streamdown v1 (header>div) and v2 (code-block-actions). */
|
|
1971
|
+
[data-streamdown="code-block-header"] button,
|
|
1972
|
+
[data-streamdown="code-block-actions"] button {
|
|
1867
1973
|
padding: 4px !important;
|
|
1868
1974
|
border: none !important;
|
|
1869
1975
|
border-radius: 4px !important;
|
|
@@ -1872,18 +1978,21 @@ code {
|
|
|
1872
1978
|
cursor: pointer;
|
|
1873
1979
|
}
|
|
1874
1980
|
|
|
1875
|
-
[data-streamdown="code-block-header"] button:hover
|
|
1981
|
+
[data-streamdown="code-block-header"] button:hover,
|
|
1982
|
+
[data-streamdown="code-block-actions"] button:hover {
|
|
1876
1983
|
opacity: 1;
|
|
1877
1984
|
background: var(--color-border) !important;
|
|
1878
1985
|
}
|
|
1879
1986
|
|
|
1880
|
-
[data-streamdown="code-block-header"] svg
|
|
1987
|
+
[data-streamdown="code-block-header"] svg,
|
|
1988
|
+
[data-streamdown="code-block-actions"] svg {
|
|
1881
1989
|
color: var(--color-muted) !important;
|
|
1882
1990
|
width: 12px !important;
|
|
1883
1991
|
height: 12px !important;
|
|
1884
1992
|
}
|
|
1885
1993
|
|
|
1886
|
-
[data-streamdown="code-block-header"] button:hover svg
|
|
1994
|
+
[data-streamdown="code-block-header"] button:hover svg,
|
|
1995
|
+
[data-streamdown="code-block-actions"] button:hover svg {
|
|
1887
1996
|
color: var(--color-text) !important;
|
|
1888
1997
|
}
|
|
1889
1998
|
|
|
@@ -6884,9 +6993,8 @@ var useChatHeader = (config) => {
|
|
|
6884
6993
|
}
|
|
6885
6994
|
if (typeof config?.alwaysOnTop === "boolean") {
|
|
6886
6995
|
setIsPinned(config.alwaysOnTop);
|
|
6887
|
-
resolvedOnPin?.(config.alwaysOnTop);
|
|
6888
6996
|
}
|
|
6889
|
-
}, [config?.alwaysOnTop
|
|
6997
|
+
}, [config?.alwaysOnTop]);
|
|
6890
6998
|
const showPin = !!resolvedOnPin || typeof config?.alwaysOnTop === "boolean";
|
|
6891
6999
|
const showClose = !!resolvedOnClose;
|
|
6892
7000
|
const logoNode = (0, import_react17.useMemo)(() => resolveLogoNode(config?.logo, "header"), [config?.logo]);
|
|
@@ -10169,7 +10277,9 @@ var HistoryList = (0, import_react36.memo)(function HistoryList2({
|
|
|
10169
10277
|
onDelete,
|
|
10170
10278
|
onLoadMore,
|
|
10171
10279
|
isDarkMode = false,
|
|
10172
|
-
strings = {}
|
|
10280
|
+
strings = {},
|
|
10281
|
+
isConversationHighlighted,
|
|
10282
|
+
highlightedLabel
|
|
10173
10283
|
}) {
|
|
10174
10284
|
const [hoveredId, setHoveredId] = (0, import_react36.useState)(null);
|
|
10175
10285
|
const loadMoreRef = (0, import_react36.useRef)(null);
|
|
@@ -10225,6 +10335,8 @@ var HistoryList = (0, import_react36.memo)(function HistoryList2({
|
|
|
10225
10335
|
conversations.map((conv) => {
|
|
10226
10336
|
const isSelected = conv.id === selectedId;
|
|
10227
10337
|
const isHovered = conv.id === hoveredId;
|
|
10338
|
+
const isHighlighted = isConversationHighlighted?.(conv) === true;
|
|
10339
|
+
const resolvedHighlightLabel = isHighlighted ? (typeof highlightedLabel === "function" ? highlightedLabel(conv) : highlightedLabel) ?? "RELATED" : null;
|
|
10228
10340
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
10229
10341
|
"div",
|
|
10230
10342
|
{
|
|
@@ -10236,21 +10348,39 @@ var HistoryList = (0, import_react36.memo)(function HistoryList2({
|
|
|
10236
10348
|
padding: "0.5rem 0.75rem",
|
|
10237
10349
|
textAlign: "left",
|
|
10238
10350
|
cursor: "pointer",
|
|
10239
|
-
transition: "background-color 0.15s ease",
|
|
10240
|
-
|
|
10351
|
+
transition: "background-color 0.15s ease, border-color 0.15s ease",
|
|
10352
|
+
border: isHighlighted ? "1px solid var(--chat-accent)" : "1px solid transparent",
|
|
10353
|
+
background: isSelected || isHovered ? colors.hover : isHighlighted ? "color-mix(in srgb, var(--chat-accent) 10%, transparent)" : "transparent"
|
|
10241
10354
|
},
|
|
10242
10355
|
onClick: () => onSelect(conv.id),
|
|
10243
10356
|
onMouseEnter: () => setHoveredId(conv.id),
|
|
10244
10357
|
onMouseLeave: () => setHoveredId(null),
|
|
10245
10358
|
children: [
|
|
10246
10359
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { minWidth: 0, flex: 1 }, children: [
|
|
10247
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.
|
|
10248
|
-
|
|
10249
|
-
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10360
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.375rem", minWidth: 0 }, children: [
|
|
10361
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: {
|
|
10362
|
+
fontSize: "0.875rem",
|
|
10363
|
+
color: colors.text,
|
|
10364
|
+
overflow: "hidden",
|
|
10365
|
+
textOverflow: "ellipsis",
|
|
10366
|
+
whiteSpace: "nowrap"
|
|
10367
|
+
}, children: conv.title || "Untitled" }),
|
|
10368
|
+
resolvedHighlightLabel && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
10369
|
+
"span",
|
|
10370
|
+
{
|
|
10371
|
+
style: {
|
|
10372
|
+
fontSize: "0.625rem",
|
|
10373
|
+
lineHeight: 1,
|
|
10374
|
+
padding: "0.2rem 0.35rem",
|
|
10375
|
+
borderRadius: 999,
|
|
10376
|
+
background: "var(--chat-accent)",
|
|
10377
|
+
color: "#fff",
|
|
10378
|
+
flexShrink: 0
|
|
10379
|
+
},
|
|
10380
|
+
children: resolvedHighlightLabel
|
|
10381
|
+
}
|
|
10382
|
+
)
|
|
10383
|
+
] }),
|
|
10254
10384
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { fontSize: "0.75rem", color: colors.muted }, children: formatRelativeTime(conv.updatedAt, strings) })
|
|
10255
10385
|
] }),
|
|
10256
10386
|
isHovered && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
@@ -10511,6 +10641,7 @@ var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
|
10511
10641
|
onError,
|
|
10512
10642
|
onMessageReceived,
|
|
10513
10643
|
onLoadingChange,
|
|
10644
|
+
onConversationChange,
|
|
10514
10645
|
onStateChange,
|
|
10515
10646
|
headerLeft,
|
|
10516
10647
|
headerRight,
|
|
@@ -10519,8 +10650,13 @@ var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
|
10519
10650
|
inputPortalContainer,
|
|
10520
10651
|
sendMessageRef,
|
|
10521
10652
|
newConversationRef,
|
|
10653
|
+
loadConversationRef,
|
|
10654
|
+
stopStreamingRef,
|
|
10522
10655
|
focusInputRef: parentFocusInputRef,
|
|
10523
10656
|
setTextRef: parentSetTextRef,
|
|
10657
|
+
controllerRef,
|
|
10658
|
+
onConversationDeleted,
|
|
10659
|
+
historyConfig,
|
|
10524
10660
|
renderMessage,
|
|
10525
10661
|
emptyState,
|
|
10526
10662
|
className = "",
|
|
@@ -10591,7 +10727,8 @@ var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
|
10591
10727
|
});
|
|
10592
10728
|
const chat = useChat({
|
|
10593
10729
|
adapter,
|
|
10594
|
-
onError
|
|
10730
|
+
onError,
|
|
10731
|
+
onConversationChange
|
|
10595
10732
|
});
|
|
10596
10733
|
useFocusPersistence({
|
|
10597
10734
|
containerRef: chatContainerRef,
|
|
@@ -10635,6 +10772,16 @@ var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
|
10635
10772
|
newConversationRef.current = chat.newConversation;
|
|
10636
10773
|
}
|
|
10637
10774
|
}, [newConversationRef, chat.newConversation]);
|
|
10775
|
+
(0, import_react38.useEffect)(() => {
|
|
10776
|
+
if (loadConversationRef) {
|
|
10777
|
+
loadConversationRef.current = chat.loadConversation;
|
|
10778
|
+
}
|
|
10779
|
+
}, [loadConversationRef, chat.loadConversation]);
|
|
10780
|
+
(0, import_react38.useEffect)(() => {
|
|
10781
|
+
if (stopStreamingRef) {
|
|
10782
|
+
stopStreamingRef.current = chat.stopStreaming;
|
|
10783
|
+
}
|
|
10784
|
+
}, [stopStreamingRef, chat.stopStreaming]);
|
|
10638
10785
|
(0, import_react38.useEffect)(() => {
|
|
10639
10786
|
if (parentFocusInputRef) {
|
|
10640
10787
|
parentFocusInputRef.current = () => chatInputRef.current?.focus();
|
|
@@ -10645,6 +10792,63 @@ var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
|
10645
10792
|
parentSetTextRef.current = (text) => chatInputRef.current?.setValue(text);
|
|
10646
10793
|
}
|
|
10647
10794
|
}, [parentSetTextRef]);
|
|
10795
|
+
const getStateSnapshot = (0, import_react38.useCallback)(() => ({
|
|
10796
|
+
messages: chat.messages,
|
|
10797
|
+
isLoading: chat.isLoading,
|
|
10798
|
+
isStreaming: chat.isStreaming,
|
|
10799
|
+
error: chat.error,
|
|
10800
|
+
conversationId: chat.conversationId,
|
|
10801
|
+
conversationTitle: chat.conversationTitle,
|
|
10802
|
+
capabilities: chat.capabilities
|
|
10803
|
+
}), [
|
|
10804
|
+
chat.messages,
|
|
10805
|
+
chat.isLoading,
|
|
10806
|
+
chat.isStreaming,
|
|
10807
|
+
chat.error,
|
|
10808
|
+
chat.conversationId,
|
|
10809
|
+
chat.conversationTitle,
|
|
10810
|
+
chat.capabilities
|
|
10811
|
+
]);
|
|
10812
|
+
(0, import_react38.useEffect)(() => {
|
|
10813
|
+
if (!controllerRef) return;
|
|
10814
|
+
controllerRef.current = {
|
|
10815
|
+
sendMessage: chat.sendMessage,
|
|
10816
|
+
trySendMessage: chat.trySendMessage,
|
|
10817
|
+
newConversation: chat.newConversation,
|
|
10818
|
+
loadConversation: chat.loadConversation,
|
|
10819
|
+
stopStreaming: chat.stopStreaming,
|
|
10820
|
+
focusInput: () => chatInputRef.current?.focus(),
|
|
10821
|
+
setInputText: (text) => chatInputRef.current?.setValue(text),
|
|
10822
|
+
getState: getStateSnapshot
|
|
10823
|
+
};
|
|
10824
|
+
}, [
|
|
10825
|
+
controllerRef,
|
|
10826
|
+
chat.sendMessage,
|
|
10827
|
+
chat.trySendMessage,
|
|
10828
|
+
chat.newConversation,
|
|
10829
|
+
chat.loadConversation,
|
|
10830
|
+
chat.stopStreaming,
|
|
10831
|
+
getStateSnapshot
|
|
10832
|
+
]);
|
|
10833
|
+
(0, import_react38.useEffect)(() => {
|
|
10834
|
+
return () => {
|
|
10835
|
+
if (sendMessageRef) sendMessageRef.current = null;
|
|
10836
|
+
if (newConversationRef) newConversationRef.current = null;
|
|
10837
|
+
if (loadConversationRef) loadConversationRef.current = null;
|
|
10838
|
+
if (stopStreamingRef) stopStreamingRef.current = null;
|
|
10839
|
+
if (parentFocusInputRef) parentFocusInputRef.current = null;
|
|
10840
|
+
if (parentSetTextRef) parentSetTextRef.current = null;
|
|
10841
|
+
if (controllerRef) controllerRef.current = null;
|
|
10842
|
+
};
|
|
10843
|
+
}, [
|
|
10844
|
+
sendMessageRef,
|
|
10845
|
+
newConversationRef,
|
|
10846
|
+
loadConversationRef,
|
|
10847
|
+
stopStreamingRef,
|
|
10848
|
+
parentFocusInputRef,
|
|
10849
|
+
parentSetTextRef,
|
|
10850
|
+
controllerRef
|
|
10851
|
+
]);
|
|
10648
10852
|
(0, import_react38.useEffect)(() => {
|
|
10649
10853
|
if (!adapter.onFocusInput) return;
|
|
10650
10854
|
return adapter.onFocusInput(() => {
|
|
@@ -10666,12 +10870,9 @@ var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
|
10666
10870
|
}, [chat.isLoading, onLoadingChange]);
|
|
10667
10871
|
(0, import_react38.useEffect)(() => {
|
|
10668
10872
|
if (onStateChange) {
|
|
10669
|
-
onStateChange(
|
|
10670
|
-
messages: chat.messages,
|
|
10671
|
-
conversationId: chat.conversationId
|
|
10672
|
-
});
|
|
10873
|
+
onStateChange(getStateSnapshot());
|
|
10673
10874
|
}
|
|
10674
|
-
}, [
|
|
10875
|
+
}, [getStateSnapshot, onStateChange]);
|
|
10675
10876
|
(0, import_react38.useEffect)(() => {
|
|
10676
10877
|
if (connection.isConnected) {
|
|
10677
10878
|
resourcePicker.refreshProviders();
|
|
@@ -10699,11 +10900,12 @@ var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
|
10699
10900
|
const handleDeleteConversation = (0, import_react38.useCallback)(
|
|
10700
10901
|
async (id) => {
|
|
10701
10902
|
await conversations.deleteConversation(id);
|
|
10903
|
+
onConversationDeleted?.(id);
|
|
10702
10904
|
if (id === chat.conversationId) {
|
|
10703
10905
|
chat.newConversation();
|
|
10704
10906
|
}
|
|
10705
10907
|
},
|
|
10706
|
-
[conversations, chat]
|
|
10908
|
+
[conversations, chat, onConversationDeleted]
|
|
10707
10909
|
);
|
|
10708
10910
|
const handleNewChat = (0, import_react38.useCallback)(() => {
|
|
10709
10911
|
chat.newConversation();
|
|
@@ -10964,6 +11166,8 @@ var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
|
10964
11166
|
onDelete: handleDeleteConversation,
|
|
10965
11167
|
onLoadMore: conversations.loadMore,
|
|
10966
11168
|
isDarkMode: resolvedIsDarkMode,
|
|
11169
|
+
isConversationHighlighted: historyConfig?.isConversationHighlighted,
|
|
11170
|
+
highlightedLabel: historyConfig?.highlightedLabel,
|
|
10967
11171
|
strings: {
|
|
10968
11172
|
noHistory: mergedStrings.noHistory,
|
|
10969
11173
|
loadMore: mergedStrings.loadMore,
|