@cntyclub/agent-react 0.14.3 → 0.15.0
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/components/agent-voice-recorder.d.ts.map +1 -1
- package/dist/components/message-item.d.ts.map +1 -1
- package/dist/components/thinking-indicator.d.ts +3 -2
- package/dist/components/thinking-indicator.d.ts.map +1 -1
- package/dist/index.js +81 -32
- package/dist/index.js.map +1 -1
- package/dist/message-group.d.ts.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/use-agent-chat.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-voice-recorder.d.ts","sourceRoot":"","sources":["../../src/components/agent-voice-recorder.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,uBAAuB;IACtC,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,4EAA4E;IAC5E,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,sEAAsE;IACtE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;
|
|
1
|
+
{"version":3,"file":"agent-voice-recorder.d.ts","sourceRoot":"","sources":["../../src/components/agent-voice-recorder.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,uBAAuB;IACtC,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,4EAA4E;IAC5E,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,sEAAsE;IACtE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AA8BD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,uBAAuB,qBAiShH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-item.d.ts","sourceRoot":"","sources":["../../src/components/message-item.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAM7C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"message-item.d.ts","sourceRoot":"","sources":["../../src/components/message-item.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAM7C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,4BAsGjE"}
|
|
@@ -7,8 +7,9 @@ export interface ThinkingIndicatorProps {
|
|
|
7
7
|
className?: string;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* A muted "typing" bubble:
|
|
11
|
-
* ~1.8s, so a long tool run reads as active progress instead of
|
|
10
|
+
* A muted "typing" bubble: an aurora-colored thinking orb plus a phrase that
|
|
11
|
+
* rotates every ~1.8s, so a long tool run reads as active progress instead of
|
|
12
|
+
* a frozen "…".
|
|
12
13
|
*/
|
|
13
14
|
export declare function ThinkingIndicator({ className, intervalMs, phrases }: ThinkingIndicatorProps): React.JSX.Element;
|
|
14
15
|
//# sourceMappingURL=thinking-indicator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thinking-indicator.d.ts","sourceRoot":"","sources":["../../src/components/thinking-indicator.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED
|
|
1
|
+
{"version":3,"file":"thinking-indicator.d.ts","sourceRoot":"","sources":["../../src/components/thinking-indicator.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,UAAiB,EAAE,OAAO,EAAE,EAAE,sBAAsB,qBAqClG"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { cn, Button, Tooltip, TooltipTrigger, TooltipContent, ChatMessage, ChatMessageBubble, Markdown,
|
|
2
|
-
import { XIcon, Trash2Icon, SquareIcon, PauseIcon, PlayIcon, CheckIcon,
|
|
1
|
+
import { cn, Button, AuroraOrb, AuroraText, Tooltip, TooltipTrigger, TooltipContent, ChatMessage, ChatMessageBubble, Markdown, Spinner, Checkbox, Collapsible, CollapsibleTrigger, ChatToolChip, CollapsiblePanel, ChatToolCard, ChatToolCardHeader, ChatToolCardActions, Group, Menu, MenuTrigger, MenuPopup, MenuItem, ChatHeader, ChatHeaderAvatar, ChatHeaderTitle, ChatHeaderActions, Chat, ChatEmptyState, ChatEmptyStateIcon, ChatEmptyStateTitle, ChatEmptyStateDescription, ChatSuggestions, ChatSuggestion, useMediaQuery, TooltipProvider, DataTablePaged } from '@cntyclub/ui-react';
|
|
2
|
+
import { XIcon, Trash2Icon, SquareIcon, PauseIcon, PlayIcon, CheckIcon, FileTextIcon, PaperclipIcon, MicIcon, ArrowUpIcon, CopyIcon, Maximize2Icon, ListChecksIcon, ChevronDownIcon, ShieldAlertIcon, CheckCheckIcon, UploadCloudIcon, HistoryIcon, SquarePenIcon, Minimize2Icon, ChevronsRightIcon, SparklesIcon, DownloadIcon, CodeIcon } from 'lucide-react';
|
|
3
3
|
import * as React11 from 'react';
|
|
4
4
|
import { AnimatePresence, motion } from 'motion/react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
@@ -312,7 +312,10 @@ function AgentImageLightbox({ src, alt, onClose }) {
|
|
|
312
312
|
document.body
|
|
313
313
|
);
|
|
314
314
|
}
|
|
315
|
-
var
|
|
315
|
+
var BAR_WIDTH = 2;
|
|
316
|
+
var BAR_GAP = 3;
|
|
317
|
+
var MAX_BARS = 1024;
|
|
318
|
+
var FADE_BARS = 12;
|
|
316
319
|
function formatClock(totalSeconds) {
|
|
317
320
|
const minutes = Math.floor(totalSeconds / 60);
|
|
318
321
|
const seconds = totalSeconds % 60;
|
|
@@ -340,7 +343,7 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
340
343
|
const audioContextRef = React11.useRef(null);
|
|
341
344
|
const analyserRef = React11.useRef(null);
|
|
342
345
|
const rafRef = React11.useRef(null);
|
|
343
|
-
const levelsRef = React11.useRef(new Array(
|
|
346
|
+
const levelsRef = React11.useRef(new Array(MAX_BARS).fill(0));
|
|
344
347
|
const onErrorRef = React11.useRef(onError);
|
|
345
348
|
onErrorRef.current = onError;
|
|
346
349
|
const stopMeter = React11.useCallback(() => {
|
|
@@ -379,7 +382,7 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
379
382
|
analyser.smoothingTimeConstant = 0.75;
|
|
380
383
|
source.connect(analyser);
|
|
381
384
|
analyserRef.current = analyser;
|
|
382
|
-
levelsRef.current = new Array(
|
|
385
|
+
levelsRef.current = new Array(MAX_BARS).fill(0);
|
|
383
386
|
const buffer = new Uint8Array(analyser.fftSize);
|
|
384
387
|
const draw = () => {
|
|
385
388
|
const canvas = canvasRef.current;
|
|
@@ -407,16 +410,19 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
407
410
|
if (canvas.height !== pxHeight) canvas.height = pxHeight;
|
|
408
411
|
ctx2d.clearRect(0, 0, pxWidth, pxHeight);
|
|
409
412
|
ctx2d.fillStyle = getComputedStyle(canvas).color || "currentColor";
|
|
410
|
-
const
|
|
411
|
-
const
|
|
413
|
+
const barWidth = BAR_WIDTH * dpr;
|
|
414
|
+
const slot = (BAR_WIDTH + BAR_GAP) * dpr;
|
|
415
|
+
const count = Math.max(1, Math.min(MAX_BARS, Math.floor((pxWidth + BAR_GAP * dpr) / slot)));
|
|
412
416
|
const midY = pxHeight / 2;
|
|
413
|
-
const minBar =
|
|
417
|
+
const minBar = barWidth;
|
|
418
|
+
const maxBar = pxHeight * 0.92;
|
|
414
419
|
const radius = barWidth / 2;
|
|
415
|
-
for (let i = 0; i <
|
|
416
|
-
const value = levels[i];
|
|
417
|
-
const barHeight = Math.max(minBar, value *
|
|
418
|
-
const x =
|
|
420
|
+
for (let i = 0; i < count; i += 1) {
|
|
421
|
+
const value = levels[levels.length - count + i];
|
|
422
|
+
const barHeight = Math.max(minBar, value * maxBar);
|
|
423
|
+
const x = pxWidth - barWidth - (count - 1 - i) * slot;
|
|
419
424
|
const y = midY - barHeight / 2;
|
|
425
|
+
ctx2d.globalAlpha = Math.min(1, (i + 1) / FADE_BARS);
|
|
420
426
|
if (typeof ctx2d.roundRect === "function") {
|
|
421
427
|
ctx2d.beginPath();
|
|
422
428
|
ctx2d.roundRect(x, y, barWidth, barHeight, Math.min(radius, barHeight / 2));
|
|
@@ -425,6 +431,7 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
425
431
|
ctx2d.fillRect(x, y, barWidth, barHeight);
|
|
426
432
|
}
|
|
427
433
|
}
|
|
434
|
+
ctx2d.globalAlpha = 1;
|
|
428
435
|
rafRef.current = requestAnimationFrame(draw);
|
|
429
436
|
};
|
|
430
437
|
rafRef.current = requestAnimationFrame(draw);
|
|
@@ -540,7 +547,7 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
540
547
|
),
|
|
541
548
|
/* @__PURE__ */ jsx("span", { className: "font-medium tabular-nums", children: formatClock(elapsed) })
|
|
542
549
|
] }),
|
|
543
|
-
/* @__PURE__ */ jsx("canvas", { "aria-hidden": true, className: "h-6 min-w-0 flex-1 text-foreground/
|
|
550
|
+
/* @__PURE__ */ jsx("canvas", { "aria-hidden": true, className: "h-6 min-w-0 flex-1 text-foreground/70", ref: canvasRef }),
|
|
544
551
|
/* @__PURE__ */ jsx(Button, { "aria-label": "Discard recording", onClick: onCancel, size: "icon-sm", type: "button", variant: "ghost", children: /* @__PURE__ */ jsx(Trash2Icon, {}) }),
|
|
545
552
|
/* @__PURE__ */ jsx(Button, { "aria-label": "Stop recording", onClick: stopRecording, size: "icon-sm", type: "button", children: /* @__PURE__ */ jsx(SquareIcon, {}) })
|
|
546
553
|
] }) : null,
|
|
@@ -552,9 +559,9 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
552
559
|
/* @__PURE__ */ jsx(Button, { "aria-label": "Discard recording", onClick: onCancel, size: "icon-sm", type: "button", variant: "ghost", children: /* @__PURE__ */ jsx(Trash2Icon, {}) }),
|
|
553
560
|
/* @__PURE__ */ jsx(Button, { "aria-label": "Use recording", className: "rounded-full before:rounded-full", onClick: () => void confirm(), size: "icon-sm", type: "button", children: /* @__PURE__ */ jsx(CheckIcon, {}) })
|
|
554
561
|
] }) : null,
|
|
555
|
-
phase === "transcribing" ? /* @__PURE__ */ jsxs("span", { className:
|
|
556
|
-
/* @__PURE__ */ jsx(
|
|
557
|
-
"Transcribing
|
|
562
|
+
phase === "transcribing" ? /* @__PURE__ */ jsxs("span", { className: "flex flex-1 items-center gap-2 font-medium text-sm", children: [
|
|
563
|
+
/* @__PURE__ */ jsx(AuroraOrb, { speed: 1, state: "working" }),
|
|
564
|
+
/* @__PURE__ */ jsx(AuroraText, { children: "Transcribing" })
|
|
558
565
|
] }) : null
|
|
559
566
|
]
|
|
560
567
|
}
|
|
@@ -809,14 +816,14 @@ function groupMessages(messages) {
|
|
|
809
816
|
for (const message of messages) {
|
|
810
817
|
if (message.role === "user") {
|
|
811
818
|
flush();
|
|
812
|
-
items.push({ key: message.id, kind: "user", message });
|
|
819
|
+
items.push({ key: message.client_key ?? message.id, kind: "user", message });
|
|
813
820
|
continue;
|
|
814
821
|
}
|
|
815
822
|
if (message.role === "assistant") {
|
|
816
823
|
const hasText = Boolean(message.content && message.content.trim());
|
|
817
824
|
if (hasText) {
|
|
818
825
|
flush();
|
|
819
|
-
items.push({ key: message.id, kind: "assistant-text", message });
|
|
826
|
+
items.push({ key: message.client_key ?? message.id, kind: "assistant-text", message });
|
|
820
827
|
}
|
|
821
828
|
for (const toolCall of message.tool_calls ?? []) {
|
|
822
829
|
const callId2 = toolCall.id ?? `${message.id}-${toolCall.name}`;
|
|
@@ -931,7 +938,7 @@ function MessageItem({ message }) {
|
|
|
931
938
|
const attachments = message.attachments ?? [];
|
|
932
939
|
const images = attachments.filter((a) => isImageAttachment(a.format) && a.url);
|
|
933
940
|
const others = attachments.filter((a) => !isImageAttachment(a.format) || !a.url);
|
|
934
|
-
return /* @__PURE__ */ jsxs(ChatMessage, { from: "user", children: [
|
|
941
|
+
return /* @__PURE__ */ jsxs(ChatMessage, { className: "group", from: "user", children: [
|
|
935
942
|
images.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap justify-end gap-1.5", children: images.map((attachment) => /* @__PURE__ */ jsx(
|
|
936
943
|
"button",
|
|
937
944
|
{
|
|
@@ -954,14 +961,37 @@ function MessageItem({ message }) {
|
|
|
954
961
|
},
|
|
955
962
|
attachment.id
|
|
956
963
|
)) }) : null,
|
|
957
|
-
message.content ? /* @__PURE__ */ jsx(ChatMessageBubble, { from: "user", children: message.content }) : null,
|
|
964
|
+
message.content ? /* @__PURE__ */ jsx(ChatMessageBubble, { className: "whitespace-pre-wrap", from: "user", children: message.content }) : null,
|
|
965
|
+
message.content ? /* @__PURE__ */ jsx(
|
|
966
|
+
"div",
|
|
967
|
+
{
|
|
968
|
+
className: cn(
|
|
969
|
+
"mt-0.5 flex justify-end opacity-0 transition-opacity",
|
|
970
|
+
"group-hover:opacity-100 focus-within:opacity-100"
|
|
971
|
+
),
|
|
972
|
+
children: /* @__PURE__ */ jsx(CopyButton, { text: message.content })
|
|
973
|
+
}
|
|
974
|
+
) : null,
|
|
958
975
|
/* @__PURE__ */ jsx(AgentImageLightbox, { onClose: () => setLightboxSrc(null), src: lightboxSrc })
|
|
959
976
|
] });
|
|
960
977
|
}
|
|
961
978
|
if (message.role === "assistant") {
|
|
962
979
|
if (!message.content || !message.content.trim()) return null;
|
|
963
980
|
return /* @__PURE__ */ jsxs(ChatMessage, { className: "group", from: "assistant", children: [
|
|
964
|
-
/* @__PURE__ */ jsx(ChatMessageBubble, { from: "assistant", children: /* @__PURE__ */ jsx(
|
|
981
|
+
/* @__PURE__ */ jsx(ChatMessageBubble, { from: "assistant", children: /* @__PURE__ */ jsx(
|
|
982
|
+
"div",
|
|
983
|
+
{
|
|
984
|
+
className: "[&_img]:cursor-zoom-in [&_img]:rounded-md",
|
|
985
|
+
onClick: (event) => {
|
|
986
|
+
const target = event.target;
|
|
987
|
+
if (target.tagName !== "IMG") return;
|
|
988
|
+
const src = target.currentSrc || target.src;
|
|
989
|
+
if (src) setLightboxSrc(src);
|
|
990
|
+
},
|
|
991
|
+
role: "presentation",
|
|
992
|
+
children: /* @__PURE__ */ jsx(Markdown, { children: message.content })
|
|
993
|
+
}
|
|
994
|
+
) }),
|
|
965
995
|
/* @__PURE__ */ jsx(
|
|
966
996
|
"div",
|
|
967
997
|
{
|
|
@@ -971,7 +1001,8 @@ function MessageItem({ message }) {
|
|
|
971
1001
|
),
|
|
972
1002
|
children: /* @__PURE__ */ jsx(CopyButton, { text: message.content })
|
|
973
1003
|
}
|
|
974
|
-
)
|
|
1004
|
+
),
|
|
1005
|
+
/* @__PURE__ */ jsx(AgentImageLightbox, { onClose: () => setLightboxSrc(null), src: lightboxSrc })
|
|
975
1006
|
] });
|
|
976
1007
|
}
|
|
977
1008
|
return null;
|
|
@@ -1005,11 +1036,7 @@ function ThinkingIndicator({ className, intervalMs = 1800, phrases }) {
|
|
|
1005
1036
|
"data-slot": "thinking-indicator",
|
|
1006
1037
|
role: "status",
|
|
1007
1038
|
children: [
|
|
1008
|
-
/* @__PURE__ */
|
|
1009
|
-
/* @__PURE__ */ jsx("span", { className: "size-1.5 animate-bounce rounded-full bg-muted-foreground/60 [animation-delay:0ms]" }),
|
|
1010
|
-
/* @__PURE__ */ jsx("span", { className: "size-1.5 animate-bounce rounded-full bg-muted-foreground/60 [animation-delay:150ms]" }),
|
|
1011
|
-
/* @__PURE__ */ jsx("span", { className: "size-1.5 animate-bounce rounded-full bg-muted-foreground/60 [animation-delay:300ms]" })
|
|
1012
|
-
] }),
|
|
1039
|
+
/* @__PURE__ */ jsx(AuroraOrb, { speed: 0.7, state: "solving" }),
|
|
1013
1040
|
/* @__PURE__ */ jsx(
|
|
1014
1041
|
"span",
|
|
1015
1042
|
{
|
|
@@ -1866,8 +1893,16 @@ function useAgentChat(config) {
|
|
|
1866
1893
|
if (response.messages?.length) {
|
|
1867
1894
|
setMessages((current) => {
|
|
1868
1895
|
const settled = current.filter((message) => !message.id.startsWith(OPTIMISTIC_ID_PREFIX));
|
|
1896
|
+
const optimistic = current.filter((message) => message.id.startsWith(OPTIMISTIC_ID_PREFIX));
|
|
1869
1897
|
const seen = new Set(settled.map((message) => message.id));
|
|
1870
1898
|
const fresh = response.messages?.filter((message) => !seen.has(message.id)) ?? [];
|
|
1899
|
+
const placeholder = optimistic[optimistic.length - 1];
|
|
1900
|
+
if (placeholder) {
|
|
1901
|
+
const echoIndex = fresh.findIndex((message) => message.role === "user");
|
|
1902
|
+
if (echoIndex !== -1) {
|
|
1903
|
+
fresh[echoIndex] = { ...fresh[echoIndex], client_key: placeholder.client_key ?? placeholder.id };
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1871
1906
|
return [...settled, ...fresh];
|
|
1872
1907
|
});
|
|
1873
1908
|
}
|
|
@@ -1887,8 +1922,13 @@ function useAgentChat(config) {
|
|
|
1887
1922
|
case "user_message":
|
|
1888
1923
|
setMessages((current) => {
|
|
1889
1924
|
const settled = current.filter((message) => !message.id.startsWith(OPTIMISTIC_ID_PREFIX));
|
|
1890
|
-
|
|
1891
|
-
|
|
1925
|
+
if (settled.some((message) => message.id === event.message.id)) return settled;
|
|
1926
|
+
const optimistic = current.filter((message) => message.id.startsWith(OPTIMISTIC_ID_PREFIX));
|
|
1927
|
+
const placeholder = optimistic[optimistic.length - 1];
|
|
1928
|
+
if (!placeholder) return [...settled, event.message];
|
|
1929
|
+
return current.filter((message) => !message.id.startsWith(OPTIMISTIC_ID_PREFIX) || message.id === placeholder.id).map(
|
|
1930
|
+
(message) => message.id === placeholder.id ? { ...event.message, client_key: placeholder.client_key ?? placeholder.id } : message
|
|
1931
|
+
);
|
|
1892
1932
|
});
|
|
1893
1933
|
break;
|
|
1894
1934
|
case "text_delta": {
|
|
@@ -1916,9 +1956,18 @@ function useAgentChat(config) {
|
|
|
1916
1956
|
const streamingId = ctx.streamingId;
|
|
1917
1957
|
ctx.streamingId = null;
|
|
1918
1958
|
setMessages((current) => {
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1959
|
+
if (current.some((message) => message.id === event.message.id)) {
|
|
1960
|
+
return streamingId ? current.filter((message) => message.id !== streamingId) : current;
|
|
1961
|
+
}
|
|
1962
|
+
if (streamingId) {
|
|
1963
|
+
const index = current.findIndex((message) => message.id === streamingId);
|
|
1964
|
+
if (index !== -1) {
|
|
1965
|
+
const next = [...current];
|
|
1966
|
+
next[index] = { ...event.message, client_key: streamingId };
|
|
1967
|
+
return next;
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
return [...current, event.message];
|
|
1922
1971
|
});
|
|
1923
1972
|
break;
|
|
1924
1973
|
}
|