yt-chat-components 1.0.0 → 1.0.2

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/index.pb +3 -31
  3. package/dist/build/static/js/bundle.min.js +1 -0
  4. package/package.json +76 -76
  5. package/public/index.html +108 -108
  6. package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +464 -464
  7. package/src/YtChatView/chatWidget/chatWindow/controllers/index.ts +249 -249
  8. package/src/YtChatView/chatWidget/chatWindow/index.module.css +196 -196
  9. package/src/YtChatView/chatWidget/chatWindow/index.tsx +1054 -1041
  10. package/src/YtChatView/chatWidget/chatWindow/types/chatWidget/index.ts +50 -50
  11. package/src/YtChatView/chatWidget/index.tsx +2586 -2586
  12. package/src/YtChatView/logoBtn/index.css +3 -3
  13. package/src/YtChatView/logoBtn/index.jsx +103 -103
  14. package/src/YtChatView/logoSplitBtn/index.css +3 -3
  15. package/src/YtChatView/logoSplitBtn/index.jsx +105 -105
  16. package/src/YtChatView/mobileChat/index.jsx +944 -848
  17. package/src/YtChatView/mobileChat/index.module.css +253 -253
  18. package/src/YtChatView/previewDialog/index.jsx +600 -600
  19. package/src/YtChatView/previewDialog/index.module.css +253 -253
  20. package/src/chatWidget/chatWindow/index.tsx +426 -426
  21. package/src/chatWidget/index.tsx +2193 -2193
  22. package/src/index.tsx +10 -10
  23. package/webpack.config.js +50 -50
  24. package/.idea/sonarlint/issuestore/3/6/364385cedcce4c06de1901392ffeeac0caef0f3c +0 -0
  25. package/.idea/sonarlint/issuestore/3/9/39129446b425a1d640160c068e4194e96639eedf +0 -0
  26. package/.idea/sonarlint/issuestore/4/a/4a2f33951ce07c1ff7184f91877aa13db05d3785 +0 -0
  27. package/.idea/sonarlint/issuestore/4/a/4a7b99bdbee5792679d347b6474463bf5e14b66d +0 -0
  28. package/.idea/sonarlint/issuestore/4/b/4b015aa5428c4d4c3d672893ec23f5fe3969f9be +0 -0
  29. package/.idea/sonarlint/issuestore/4/b/4b6989b8ccae808ebc45d02230d336ea53800365 +0 -0
  30. package/.idea/sonarlint/issuestore/6/1/61ebb9fd6e8cf9082658121d5d81e297791dacd0 +0 -0
  31. package/.idea/sonarlint/issuestore/6/c/6c024c1d0ad64656b9d4b0695ec3c49c0454addf +0 -0
  32. package/.idea/sonarlint/issuestore/6/e/6e75fc1c07c3a427a86fc213ca9479caaaff00ea +0 -0
  33. package/.idea/sonarlint/issuestore/8/d/8d6123af13a140f93e06299fff7ea23c547e9ec8 +0 -0
  34. package/.idea/sonarlint/issuestore/c/c/cc2352788140b6778ac06df4b33f50b390d2d8be +0 -0
  35. package/.idea/sonarlint/issuestore/d/5/d5595158cc48f9bf3e51b06f6e6805a8fd2d6262 +0 -0
  36. package/.idea/sonarlint/issuestore/d/7/d747cbed4201192dfa83a1a51345b020a050b647 +0 -0
  37. package/.idea/sonarlint/issuestore/d/9/d938938695d447dadda115e28781c6541f53fc4f +0 -0
  38. package/build/static/js/bundle.min.js +0 -2
  39. package/build/static/js/bundle.min.js.LICENSE.txt +0 -132
  40. /package/.idea/{langflow-embedded-chat.iml → langflow-embedded-chat-clone.iml} +0 -0
  41. /package/.idea/sonarlint/issuestore/{0/f/0f8c0c92cf798431ebb931ff6e997b1af86ecee5 → 7/0/7030d0b2f71b999ff89a343de08c414af32fc93a} +0 -0
  42. /package/.idea/sonarlint/issuestore/{2/7/27e69cb561aeea20c1afbdd32d260dd60b89a81b → 9/c/9cfff9a6d27bd6c255aa751213163c7901fb8ce7} +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
+ }