yt-chat-components 1.1.1 → 1.1.3

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.
Files changed (42) hide show
  1. package/.idea/modules.xml +1 -1
  2. package/.idea/sonarlint/issuestore/3/6/364385cedcce4c06de1901392ffeeac0caef0f3c +0 -0
  3. package/.idea/sonarlint/issuestore/3/9/39129446b425a1d640160c068e4194e96639eedf +0 -0
  4. package/.idea/sonarlint/issuestore/4/a/4a2f33951ce07c1ff7184f91877aa13db05d3785 +0 -0
  5. package/.idea/sonarlint/issuestore/4/a/4a7b99bdbee5792679d347b6474463bf5e14b66d +0 -0
  6. package/.idea/sonarlint/issuestore/4/b/4b015aa5428c4d4c3d672893ec23f5fe3969f9be +0 -0
  7. package/.idea/sonarlint/issuestore/4/b/4b6989b8ccae808ebc45d02230d336ea53800365 +0 -0
  8. package/.idea/sonarlint/issuestore/6/1/61ebb9fd6e8cf9082658121d5d81e297791dacd0 +0 -0
  9. package/.idea/sonarlint/issuestore/6/c/6c024c1d0ad64656b9d4b0695ec3c49c0454addf +0 -0
  10. package/.idea/sonarlint/issuestore/6/e/6e75fc1c07c3a427a86fc213ca9479caaaff00ea +0 -0
  11. package/.idea/sonarlint/issuestore/8/d/8d6123af13a140f93e06299fff7ea23c547e9ec8 +0 -0
  12. package/.idea/sonarlint/issuestore/c/c/cc2352788140b6778ac06df4b33f50b390d2d8be +0 -0
  13. package/.idea/sonarlint/issuestore/d/5/d5595158cc48f9bf3e51b06f6e6805a8fd2d6262 +0 -0
  14. package/.idea/sonarlint/issuestore/d/7/d747cbed4201192dfa83a1a51345b020a050b647 +0 -0
  15. package/.idea/sonarlint/issuestore/d/9/d938938695d447dadda115e28781c6541f53fc4f +0 -0
  16. package/.idea/sonarlint/issuestore/index.pb +31 -3
  17. package/build/static/js/bundle.min.js +2 -0
  18. package/build/static/js/bundle.min.js.LICENSE.txt +132 -0
  19. package/package.json +79 -78
  20. package/public/index.html +108 -108
  21. package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +498 -464
  22. package/src/YtChatView/chatWidget/chatWindow/controllers/index.ts +249 -249
  23. package/src/YtChatView/chatWidget/chatWindow/index.module.css +196 -196
  24. package/src/YtChatView/chatWidget/chatWindow/index.tsx +1099 -1086
  25. package/src/YtChatView/chatWidget/chatWindow/types/chatWidget/index.ts +50 -50
  26. package/src/YtChatView/chatWidget/index.tsx +2593 -2591
  27. package/src/YtChatView/logoBtn/index.css +3 -3
  28. package/src/YtChatView/logoBtn/index.jsx +103 -103
  29. package/src/YtChatView/logoSplitBtn/index.css +3 -3
  30. package/src/YtChatView/logoSplitBtn/index.jsx +105 -105
  31. package/src/YtChatView/mobileChat/index.jsx +945 -946
  32. package/src/YtChatView/mobileChat/index.module.css +253 -253
  33. package/src/YtChatView/previewDialog/index.jsx +600 -600
  34. package/src/YtChatView/previewDialog/index.module.css +253 -253
  35. package/src/chatWidget/chatWindow/index.tsx +426 -426
  36. package/src/chatWidget/index.tsx +2193 -2193
  37. package/src/index.tsx +10 -10
  38. package/webpack.config.js +50 -50
  39. package/dist/build/static/js/bundle.min.js +0 -1
  40. /package/.idea/{langflow-embedded-chat-clone.iml → langflow-embedded-chat.iml} +0 -0
  41. /package/.idea/sonarlint/issuestore/{7/0/7030d0b2f71b999ff89a343de08c414af32fc93a → 0/f/0f8c0c92cf798431ebb931ff6e997b1af86ecee5} +0 -0
  42. /package/.idea/sonarlint/issuestore/{9/c/9cfff9a6d27bd6c255aa751213163c7901fb8ce7 → 2/7/27e69cb561aeea20c1afbdd32d260dd60b89a81b} +0 -0
@@ -1,426 +1,426 @@
1
- // @ts-nocheck
2
- import { Send } from "lucide-react";
3
- import { extractMessageFromOutput, getAnimationOrigin, getChatPosition } from "../utils";
4
- import React, { useEffect, useRef, useState } from "react";
5
- import { ChatMessageType } from "../../types/chatWidget";
6
- import ChatMessage from "./chatMessage";
7
- import {sendMessage, sendMessageStream} from "../../controllers";
8
- import ChatMessagePlaceholder from "../../chatPlaceholder";
9
-
10
- export default function ChatWindow({
11
- api_key,
12
- flowId,
13
- hostUrl,
14
- updateLastMessage,
15
- messages,
16
- output_type,
17
- input_type,
18
- output_component,
19
- bot_message_style,
20
- send_icon_style,
21
- user_message_style,
22
- chat_window_style,
23
- error_message_style,
24
- placeholder_sending,
25
- send_button_style,
26
- online = true,
27
- open,
28
- online_message = "We'll reply as soon as we can",
29
- offline_message = "We're offline now",
30
- window_title = "Chat",
31
- placeholder,
32
- input_style,
33
- input_container_style,
34
- addMessage,
35
- position,
36
- triggerRef,
37
- width = 450,
38
- height = 650,
39
- tweaks,
40
- sessionId,
41
- additional_headers
42
- }: {
43
- api_key?: string;
44
- output_type: string,
45
- input_type: string,
46
- output_component?: string,
47
- bot_message_style?: React.CSSProperties;
48
- send_icon_style?: React.CSSProperties;
49
- user_message_style?: React.CSSProperties;
50
- chat_window_style?: React.CSSProperties;
51
- error_message_style?: React.CSSProperties;
52
- send_button_style?: React.CSSProperties;
53
- online?: boolean;
54
- open: boolean;
55
- online_message?: string;
56
- placeholder_sending?: string;
57
- offline_message?: string;
58
- window_title?: string;
59
- placeholder?: string;
60
- input_style?: React.CSSProperties;
61
- input_container_style?: React.CSSProperties;
62
- tweaks?: { [key: string]: any };
63
- flowId: string;
64
- hostUrl: string;
65
- updateLastMessage: Function;
66
- messages: ChatMessageType[];
67
- addMessage: Function;
68
- position?: string;
69
- triggerRef: React.RefObject<HTMLButtonElement>;
70
- width?: number;
71
- height?: number;
72
- sessionId: React.MutableRefObject<string>;
73
- additional_headers?: { [key: string]: string };
74
-
75
- }) {
76
- const [value, setValue] = useState<string>("");
77
- const ref = useRef<HTMLDivElement>(null);
78
- const lastMessage = useRef<HTMLDivElement>(null);
79
- const [windowPosition, setWindowPosition] = useState({ left: "0", top: "0" });
80
- const abortControllerRef = useRef(new AbortController());
81
- const inputRef = useRef<HTMLInputElement>(null); /* User input Ref */
82
- useEffect(() => {
83
- if (triggerRef)
84
- setWindowPosition(
85
- getChatPosition(
86
- triggerRef.current!.getBoundingClientRect(),
87
- width,
88
- height,
89
- position
90
- )
91
- );
92
- }, [triggerRef, width, height, position]);
93
-
94
- const isStream = true;
95
-
96
- /* Initial listener for loss of focus that refocuses User input after a small delay */
97
-
98
- const [sendingMessage, setSendingMessage] = useState(false);
99
-
100
- // 流式输出消息,实时显示(token为流式输出内容,end为结束输出,整体输出一次)
101
- const handleMessageContent = (event, data) => {
102
- if (event == 'add_message' && data['sender'] == 'Machine') {
103
- getHistoryList();
104
- } else if (event == 'token') {
105
- setNowAIContent((prevState) => prevState + data['chunk']);
106
- if (lastMessage.current) lastMessage.current.scrollIntoView({ behavior: 'smooth' });
107
- } else if (event == 'end') {
108
- const res = {
109
- data: data['result'],
110
- };
111
- if (
112
- res.data &&
113
- res.data.outputs &&
114
- Object.keys(res.data.outputs).length > 0 &&
115
- res.data.outputs[0].outputs &&
116
- res.data.outputs[0].outputs.length > 0
117
- ) {
118
- const flowOutputs: Array<any> = res.data.outputs[0].outputs;
119
- if (output_component && flowOutputs.map((e) => e.component_id).includes(output_component)) {
120
- Object.values(
121
- flowOutputs.find((e) => e.component_id === output_component).outputs,
122
- ).forEach((output: any) => {
123
- addMessage({
124
- message: extractMessageFromOutput(output),
125
- isSend: false,
126
- rawInfo: output.message,
127
- });
128
- });
129
- } else if (flowOutputs.length === 1) {
130
- Object.values(flowOutputs[0].outputs).forEach((output: any) => {
131
- addMessage({
132
- message: extractMessageFromOutput(output),
133
- isSend: false,
134
- rawInfo: output.message,
135
- });
136
- });
137
- } else {
138
- flowOutputs
139
- .sort((a, b) => {
140
- // Get the earliest timestamp from each flowOutput's outputs
141
- const aTimestamp = Math.min(
142
- ...Object.values(a.outputs).map((output: any) =>
143
- Date.parse(output.message?.timestamp),
144
- ),
145
- );
146
- const bTimestamp = Math.min(
147
- ...Object.values(b.outputs).map((output: any) =>
148
- Date.parse(output.message?.timestamp),
149
- ),
150
- );
151
- return aTimestamp - bTimestamp; // Sort descending (newest first)
152
- })
153
- .forEach((flowOutput) => {
154
- Object.values(flowOutput.outputs).forEach((output: any) => {
155
- addMessage({
156
- message: extractMessageFromOutput(output),
157
- isSend: false,
158
- rawInfo: output.message,
159
- });
160
- });
161
- });
162
- }
163
- }
164
- if (res.data && res.data.session_id) {
165
- // sessionId = res.data.session_id;
166
- }
167
- setSendingMessage(false);
168
- }
169
- };
170
-
171
- const sendMessageWrapper =()=>{
172
- sendMessage(hostUrl, flowId, value, input_type, output_type, sessionId, output_component, tweaks, api_key, additional_headers)
173
- .then((res) => {
174
- if (
175
- res.data &&
176
- res.data.outputs &&
177
- Object.keys(res.data.outputs).length > 0 &&
178
- res.data.outputs[0].outputs && res.data.outputs[0].outputs.length > 0
179
- ) {
180
- const flowOutputs: Array<any> = res.data.outputs[0].outputs;
181
- if (output_component &&
182
- flowOutputs.map(e => e.component_id).includes(output_component)) {
183
- Object.values(flowOutputs.find(e => e.component_id === output_component).outputs).forEach((output: any) => {
184
- addMessage({
185
- message: extractMessageFromOutput(output),
186
- isSend: false,
187
- });
188
- })
189
- } else if (
190
- flowOutputs.length === 1
191
- ) {
192
- Object.values(flowOutputs[0].outputs).forEach((output: any) => {
193
- addMessage({
194
- message: extractMessageFromOutput(output),
195
- isSend: false,
196
- });
197
- })
198
- } else {
199
- flowOutputs
200
- .sort((a, b) => {
201
- // Get the earliest timestamp from each flowOutput's outputs
202
- const aTimestamp = Math.min(...Object.values(a.outputs).map((output: any) => Date.parse(output.message?.timestamp)));
203
- const bTimestamp = Math.min(...Object.values(b.outputs).map((output: any) => Date.parse(output.message?.timestamp)));
204
- return aTimestamp - bTimestamp; // Sort descending (newest first)
205
- })
206
- .forEach((flowOutput) => {
207
- Object.values(flowOutput.outputs).forEach((output: any) => {
208
- addMessage({
209
- message: extractMessageFromOutput(output),
210
- isSend: false,
211
- });
212
- });
213
- });
214
- }
215
- }
216
- if (res.data && res.data.session_id) {
217
- sessionId.current = res.data.session_id;
218
- }
219
- setSendingMessage(false);
220
- })
221
- .catch((err) => {
222
- const response = err.response;
223
- if (err.code === "ERR_NETWORK") {
224
- updateLastMessage({
225
- message: "Network error",
226
- isSend: false,
227
- error: true,
228
- });
229
- } else if (
230
- response &&
231
- response.status === 500 &&
232
- response.data &&
233
- response.data.detail
234
- ) {
235
- updateLastMessage({
236
- message: response.data.detail,
237
- isSend: false,
238
- error: true,
239
- });
240
- }
241
- console.error(err);
242
- setSendingMessage(false);
243
- });
244
- }
245
-
246
- const sendMessageStreamWrapper = ()=>{
247
- let embedAppExtend: embedAppExtend = {
248
- operator_id: "2204411202",
249
- upload_file_path_list: [],
250
- http_extend: {
251
- bd:{
252
- code: "2204411202"
253
- },
254
- body: {
255
- code: "2204411202"
256
- }
257
- }
258
- };
259
- sendMessageStream(
260
- embedAppExtend,
261
- false,
262
- handleMessageContent,
263
- abortControllerRef.current.signal,
264
- hostUrl,
265
- flowId,
266
- value,
267
- input_type,
268
- output_type,
269
- sessionId.current,
270
- output_component,
271
- tweaks,
272
- api_key,
273
- additional_headers,
274
- )
275
- .then((res) => {
276
- setSendingMessage(false);
277
- })
278
- .catch((e) => {
279
- console.log('e :>> ', e);
280
- if (e.name !== 'AbortError') {
281
- addMessage({
282
- message: '网络错误',
283
- isSend: false,
284
- });
285
- }
286
- setSendingMessage(false);
287
- })
288
- }
289
- function handleClick() {
290
- if (value && value.trim() !== "") {
291
- addMessage({ message: value, isSend: true });
292
- setSendingMessage(true);
293
- setValue("");
294
- isStream ? sendMessageStreamWrapper() : sendMessageWrapper();
295
- }
296
- }
297
-
298
- useEffect(() => {
299
- if (lastMessage.current)
300
- lastMessage.current.scrollIntoView({ behavior: "smooth" });
301
- }, [messages]);
302
-
303
- /* Refocus the User input whenever a new response is returned from the LLM */
304
-
305
- useEffect(() => {
306
- // after a slight delay
307
- setTimeout(() => {
308
- inputRef.current?.focus();
309
- }, 100);
310
- }, [messages, open]);
311
-
312
- // console.log("---->",{
313
- // api_key,
314
- // flowId,
315
- // hostUrl,
316
- // updateLastMessage,
317
- // messages,
318
- // output_type,
319
- // input_type,
320
- // output_component,
321
- // bot_message_style,
322
- // send_icon_style,
323
- // user_message_style,
324
- // chat_window_style,
325
- // error_message_style,
326
- // placeholder_sending,
327
- // send_button_style,
328
- // online,
329
- // open,
330
- // online_message,
331
- // offline_message,
332
- // window_title,
333
- // placeholder,
334
- // input_style,
335
- // input_container_style,
336
- // addMessage,
337
- // position,
338
- // triggerRef,
339
- // width,
340
- // height,
341
- // tweaks,
342
- // sessionId,
343
- // additional_headers
344
- // })
345
-
346
- return (
347
- <div
348
- className={
349
- "cl-chat-window " +
350
- getAnimationOrigin(position) +
351
- (open ? " cl-scale-100" : " cl-scale-0")
352
- }
353
- style={{ ...windowPosition, zIndex: 9999 }}
354
- >
355
- <div
356
- style={{ ...chat_window_style, width: width, height: height }}
357
- ref={ref}
358
- className="cl-window"
359
- >
360
- <div className="cl-header">
361
- {window_title}
362
- <div className="cl-header-subtitle">
363
- {online ? (
364
- <>
365
- <div className="cl-online-message"></div>
366
- {online_message}
367
- </>
368
- ) : (
369
- <>
370
- <div className="cl-offline-message"></div>
371
- {offline_message}
372
- </>
373
- )}
374
- </div>
375
- </div>
376
- <div className="cl-messages_container">
377
- {messages.map((message, index) => (
378
- <ChatMessage
379
- bot_message_style={bot_message_style}
380
- user_message_style={user_message_style}
381
- error_message_style={error_message_style}
382
- key={index}
383
- message={message.message}
384
- isSend={message.isSend}
385
- error={message.error}
386
- />
387
- ))}
388
- {sendingMessage && (
389
- <ChatMessagePlaceholder bot_message_style={bot_message_style} />
390
- )}
391
- <div ref={lastMessage}></div>
392
- </div>
393
- <div style={input_container_style} className="cl-input_container">
394
- <input
395
- value={value}
396
- onChange={(e) => setValue(e.target.value)}
397
- onKeyDown={(e) => {
398
- if (e.key === "Enter") handleClick();
399
- }}
400
- type="text"
401
- disabled={sendingMessage}
402
- placeholder={sendingMessage ? (placeholder_sending || "Thinking...") : (placeholder || "Type your message...")}
403
- style={input_style}
404
- ref={inputRef}
405
- className="cl-input-element"
406
- />
407
- <button
408
- style={send_button_style}
409
- disabled={sendingMessage}
410
- onClick={handleClick}
411
- >
412
- <Send
413
- style={send_icon_style}
414
- className={
415
- "cl-send-icon " +
416
- (!sendingMessage
417
- ? "cl-notsending-message"
418
- : "cl-sending-message")
419
- }
420
- />
421
- </button>
422
- </div>
423
- </div>
424
- </div>
425
- );
426
- }
1
+ // @ts-nocheck
2
+ import { Send } from "lucide-react";
3
+ import { extractMessageFromOutput, getAnimationOrigin, getChatPosition } from "../utils";
4
+ import React, { useEffect, useRef, useState } from "react";
5
+ import { ChatMessageType } from "../../types/chatWidget";
6
+ import ChatMessage from "./chatMessage";
7
+ import {sendMessage, sendMessageStream} from "../../controllers";
8
+ import ChatMessagePlaceholder from "../../chatPlaceholder";
9
+
10
+ export default function ChatWindow({
11
+ api_key,
12
+ flowId,
13
+ hostUrl,
14
+ updateLastMessage,
15
+ messages,
16
+ output_type,
17
+ input_type,
18
+ output_component,
19
+ bot_message_style,
20
+ send_icon_style,
21
+ user_message_style,
22
+ chat_window_style,
23
+ error_message_style,
24
+ placeholder_sending,
25
+ send_button_style,
26
+ online = true,
27
+ open,
28
+ online_message = "We'll reply as soon as we can",
29
+ offline_message = "We're offline now",
30
+ window_title = "Chat",
31
+ placeholder,
32
+ input_style,
33
+ input_container_style,
34
+ addMessage,
35
+ position,
36
+ triggerRef,
37
+ width = 450,
38
+ height = 650,
39
+ tweaks,
40
+ sessionId,
41
+ additional_headers
42
+ }: {
43
+ api_key?: string;
44
+ output_type: string,
45
+ input_type: string,
46
+ output_component?: string,
47
+ bot_message_style?: React.CSSProperties;
48
+ send_icon_style?: React.CSSProperties;
49
+ user_message_style?: React.CSSProperties;
50
+ chat_window_style?: React.CSSProperties;
51
+ error_message_style?: React.CSSProperties;
52
+ send_button_style?: React.CSSProperties;
53
+ online?: boolean;
54
+ open: boolean;
55
+ online_message?: string;
56
+ placeholder_sending?: string;
57
+ offline_message?: string;
58
+ window_title?: string;
59
+ placeholder?: string;
60
+ input_style?: React.CSSProperties;
61
+ input_container_style?: React.CSSProperties;
62
+ tweaks?: { [key: string]: any };
63
+ flowId: string;
64
+ hostUrl: string;
65
+ updateLastMessage: Function;
66
+ messages: ChatMessageType[];
67
+ addMessage: Function;
68
+ position?: string;
69
+ triggerRef: React.RefObject<HTMLButtonElement>;
70
+ width?: number;
71
+ height?: number;
72
+ sessionId: React.MutableRefObject<string>;
73
+ additional_headers?: { [key: string]: string };
74
+
75
+ }) {
76
+ const [value, setValue] = useState<string>("");
77
+ const ref = useRef<HTMLDivElement>(null);
78
+ const lastMessage = useRef<HTMLDivElement>(null);
79
+ const [windowPosition, setWindowPosition] = useState({ left: "0", top: "0" });
80
+ const abortControllerRef = useRef(new AbortController());
81
+ const inputRef = useRef<HTMLInputElement>(null); /* User input Ref */
82
+ useEffect(() => {
83
+ if (triggerRef)
84
+ setWindowPosition(
85
+ getChatPosition(
86
+ triggerRef.current!.getBoundingClientRect(),
87
+ width,
88
+ height,
89
+ position
90
+ )
91
+ );
92
+ }, [triggerRef, width, height, position]);
93
+
94
+ const isStream = true;
95
+
96
+ /* Initial listener for loss of focus that refocuses User input after a small delay */
97
+
98
+ const [sendingMessage, setSendingMessage] = useState(false);
99
+
100
+ // 流式输出消息,实时显示(token为流式输出内容,end为结束输出,整体输出一次)
101
+ const handleMessageContent = (event, data) => {
102
+ if (event == 'add_message' && data['sender'] == 'Machine') {
103
+ getHistoryList();
104
+ } else if (event == 'token') {
105
+ setNowAIContent((prevState) => prevState + data['chunk']);
106
+ if (lastMessage.current) lastMessage.current.scrollIntoView({ behavior: 'smooth' });
107
+ } else if (event == 'end') {
108
+ const res = {
109
+ data: data['result'],
110
+ };
111
+ if (
112
+ res.data &&
113
+ res.data.outputs &&
114
+ Object.keys(res.data.outputs).length > 0 &&
115
+ res.data.outputs[0].outputs &&
116
+ res.data.outputs[0].outputs.length > 0
117
+ ) {
118
+ const flowOutputs: Array<any> = res.data.outputs[0].outputs;
119
+ if (output_component && flowOutputs.map((e) => e.component_id).includes(output_component)) {
120
+ Object.values(
121
+ flowOutputs.find((e) => e.component_id === output_component).outputs,
122
+ ).forEach((output: any) => {
123
+ addMessage({
124
+ message: extractMessageFromOutput(output),
125
+ isSend: false,
126
+ rawInfo: output.message,
127
+ });
128
+ });
129
+ } else if (flowOutputs.length === 1) {
130
+ Object.values(flowOutputs[0].outputs).forEach((output: any) => {
131
+ addMessage({
132
+ message: extractMessageFromOutput(output),
133
+ isSend: false,
134
+ rawInfo: output.message,
135
+ });
136
+ });
137
+ } else {
138
+ flowOutputs
139
+ .sort((a, b) => {
140
+ // Get the earliest timestamp from each flowOutput's outputs
141
+ const aTimestamp = Math.min(
142
+ ...Object.values(a.outputs).map((output: any) =>
143
+ Date.parse(output.message?.timestamp),
144
+ ),
145
+ );
146
+ const bTimestamp = Math.min(
147
+ ...Object.values(b.outputs).map((output: any) =>
148
+ Date.parse(output.message?.timestamp),
149
+ ),
150
+ );
151
+ return aTimestamp - bTimestamp; // Sort descending (newest first)
152
+ })
153
+ .forEach((flowOutput) => {
154
+ Object.values(flowOutput.outputs).forEach((output: any) => {
155
+ addMessage({
156
+ message: extractMessageFromOutput(output),
157
+ isSend: false,
158
+ rawInfo: output.message,
159
+ });
160
+ });
161
+ });
162
+ }
163
+ }
164
+ if (res.data && res.data.session_id) {
165
+ // sessionId = res.data.session_id;
166
+ }
167
+ setSendingMessage(false);
168
+ }
169
+ };
170
+
171
+ const sendMessageWrapper =()=>{
172
+ sendMessage(hostUrl, flowId, value, input_type, output_type, sessionId, output_component, tweaks, api_key, additional_headers)
173
+ .then((res) => {
174
+ if (
175
+ res.data &&
176
+ res.data.outputs &&
177
+ Object.keys(res.data.outputs).length > 0 &&
178
+ res.data.outputs[0].outputs && res.data.outputs[0].outputs.length > 0
179
+ ) {
180
+ const flowOutputs: Array<any> = res.data.outputs[0].outputs;
181
+ if (output_component &&
182
+ flowOutputs.map(e => e.component_id).includes(output_component)) {
183
+ Object.values(flowOutputs.find(e => e.component_id === output_component).outputs).forEach((output: any) => {
184
+ addMessage({
185
+ message: extractMessageFromOutput(output),
186
+ isSend: false,
187
+ });
188
+ })
189
+ } else if (
190
+ flowOutputs.length === 1
191
+ ) {
192
+ Object.values(flowOutputs[0].outputs).forEach((output: any) => {
193
+ addMessage({
194
+ message: extractMessageFromOutput(output),
195
+ isSend: false,
196
+ });
197
+ })
198
+ } else {
199
+ flowOutputs
200
+ .sort((a, b) => {
201
+ // Get the earliest timestamp from each flowOutput's outputs
202
+ const aTimestamp = Math.min(...Object.values(a.outputs).map((output: any) => Date.parse(output.message?.timestamp)));
203
+ const bTimestamp = Math.min(...Object.values(b.outputs).map((output: any) => Date.parse(output.message?.timestamp)));
204
+ return aTimestamp - bTimestamp; // Sort descending (newest first)
205
+ })
206
+ .forEach((flowOutput) => {
207
+ Object.values(flowOutput.outputs).forEach((output: any) => {
208
+ addMessage({
209
+ message: extractMessageFromOutput(output),
210
+ isSend: false,
211
+ });
212
+ });
213
+ });
214
+ }
215
+ }
216
+ if (res.data && res.data.session_id) {
217
+ sessionId.current = res.data.session_id;
218
+ }
219
+ setSendingMessage(false);
220
+ })
221
+ .catch((err) => {
222
+ const response = err.response;
223
+ if (err.code === "ERR_NETWORK") {
224
+ updateLastMessage({
225
+ message: "Network error",
226
+ isSend: false,
227
+ error: true,
228
+ });
229
+ } else if (
230
+ response &&
231
+ response.status === 500 &&
232
+ response.data &&
233
+ response.data.detail
234
+ ) {
235
+ updateLastMessage({
236
+ message: response.data.detail,
237
+ isSend: false,
238
+ error: true,
239
+ });
240
+ }
241
+ console.error(err);
242
+ setSendingMessage(false);
243
+ });
244
+ }
245
+
246
+ const sendMessageStreamWrapper = ()=>{
247
+ let embedAppExtend: embedAppExtend = {
248
+ operator_id: "2204411202",
249
+ upload_file_path_list: [],
250
+ http_extend: {
251
+ bd:{
252
+ code: "2204411202"
253
+ },
254
+ body: {
255
+ code: "2204411202"
256
+ }
257
+ }
258
+ };
259
+ sendMessageStream(
260
+ embedAppExtend,
261
+ false,
262
+ handleMessageContent,
263
+ abortControllerRef.current.signal,
264
+ hostUrl,
265
+ flowId,
266
+ value,
267
+ input_type,
268
+ output_type,
269
+ sessionId.current,
270
+ output_component,
271
+ tweaks,
272
+ api_key,
273
+ additional_headers,
274
+ )
275
+ .then((res) => {
276
+ setSendingMessage(false);
277
+ })
278
+ .catch((e) => {
279
+ console.log('e :>> ', e);
280
+ if (e.name !== 'AbortError') {
281
+ addMessage({
282
+ message: '网络错误',
283
+ isSend: false,
284
+ });
285
+ }
286
+ setSendingMessage(false);
287
+ })
288
+ }
289
+ function handleClick() {
290
+ if (value && value.trim() !== "") {
291
+ addMessage({ message: value, isSend: true });
292
+ setSendingMessage(true);
293
+ setValue("");
294
+ isStream ? sendMessageStreamWrapper() : sendMessageWrapper();
295
+ }
296
+ }
297
+
298
+ useEffect(() => {
299
+ if (lastMessage.current)
300
+ lastMessage.current.scrollIntoView({ behavior: "smooth" });
301
+ }, [messages]);
302
+
303
+ /* Refocus the User input whenever a new response is returned from the LLM */
304
+
305
+ useEffect(() => {
306
+ // after a slight delay
307
+ setTimeout(() => {
308
+ inputRef.current?.focus();
309
+ }, 100);
310
+ }, [messages, open]);
311
+
312
+ // console.log("---->",{
313
+ // api_key,
314
+ // flowId,
315
+ // hostUrl,
316
+ // updateLastMessage,
317
+ // messages,
318
+ // output_type,
319
+ // input_type,
320
+ // output_component,
321
+ // bot_message_style,
322
+ // send_icon_style,
323
+ // user_message_style,
324
+ // chat_window_style,
325
+ // error_message_style,
326
+ // placeholder_sending,
327
+ // send_button_style,
328
+ // online,
329
+ // open,
330
+ // online_message,
331
+ // offline_message,
332
+ // window_title,
333
+ // placeholder,
334
+ // input_style,
335
+ // input_container_style,
336
+ // addMessage,
337
+ // position,
338
+ // triggerRef,
339
+ // width,
340
+ // height,
341
+ // tweaks,
342
+ // sessionId,
343
+ // additional_headers
344
+ // })
345
+
346
+ return (
347
+ <div
348
+ className={
349
+ "cl-chat-window " +
350
+ getAnimationOrigin(position) +
351
+ (open ? " cl-scale-100" : " cl-scale-0")
352
+ }
353
+ style={{ ...windowPosition, zIndex: 9999 }}
354
+ >
355
+ <div
356
+ style={{ ...chat_window_style, width: width, height: height }}
357
+ ref={ref}
358
+ className="cl-window"
359
+ >
360
+ <div className="cl-header">
361
+ {window_title}
362
+ <div className="cl-header-subtitle">
363
+ {online ? (
364
+ <>
365
+ <div className="cl-online-message"></div>
366
+ {online_message}
367
+ </>
368
+ ) : (
369
+ <>
370
+ <div className="cl-offline-message"></div>
371
+ {offline_message}
372
+ </>
373
+ )}
374
+ </div>
375
+ </div>
376
+ <div className="cl-messages_container">
377
+ {messages.map((message, index) => (
378
+ <ChatMessage
379
+ bot_message_style={bot_message_style}
380
+ user_message_style={user_message_style}
381
+ error_message_style={error_message_style}
382
+ key={index}
383
+ message={message.message}
384
+ isSend={message.isSend}
385
+ error={message.error}
386
+ />
387
+ ))}
388
+ {sendingMessage && (
389
+ <ChatMessagePlaceholder bot_message_style={bot_message_style} />
390
+ )}
391
+ <div ref={lastMessage}></div>
392
+ </div>
393
+ <div style={input_container_style} className="cl-input_container">
394
+ <input
395
+ value={value}
396
+ onChange={(e) => setValue(e.target.value)}
397
+ onKeyDown={(e) => {
398
+ if (e.key === "Enter") handleClick();
399
+ }}
400
+ type="text"
401
+ disabled={sendingMessage}
402
+ placeholder={sendingMessage ? (placeholder_sending || "Thinking...") : (placeholder || "Type your message...")}
403
+ style={input_style}
404
+ ref={inputRef}
405
+ className="cl-input-element"
406
+ />
407
+ <button
408
+ style={send_button_style}
409
+ disabled={sendingMessage}
410
+ onClick={handleClick}
411
+ >
412
+ <Send
413
+ style={send_icon_style}
414
+ className={
415
+ "cl-send-icon " +
416
+ (!sendingMessage
417
+ ? "cl-notsending-message"
418
+ : "cl-sending-message")
419
+ }
420
+ />
421
+ </button>
422
+ </div>
423
+ </div>
424
+ </div>
425
+ );
426
+ }