yt-chat-components 1.2.1 → 1.2.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 (41) hide show
  1. package/.idea/sonarlint/issuestore/index.pb +0 -7
  2. package/package.json +78 -80
  3. package/public/index.html +108 -108
  4. package/src/YtChatView/chatWidget/chatWindow/callInterface/index.module.css +50 -50
  5. package/src/YtChatView/chatWidget/chatWindow/callInterface/index.tsx +549 -549
  6. package/src/YtChatView/chatWidget/chatWindow/callInterface/style.ts +44 -44
  7. package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +501 -501
  8. package/src/YtChatView/chatWidget/chatWindow/chatPlaceholder/index.tsx +23 -23
  9. package/src/YtChatView/chatWidget/chatWindow/controllers/index.ts +249 -249
  10. package/src/YtChatView/chatWidget/chatWindow/index.module.css +196 -196
  11. package/src/YtChatView/chatWidget/chatWindow/index.tsx +1186 -1185
  12. package/src/YtChatView/chatWidget/chatWindow/types/chatWidget/index.ts +50 -50
  13. package/src/YtChatView/chatWidget/index.tsx +2596 -2596
  14. package/src/YtChatView/logoBtn/index.css +3 -3
  15. package/src/YtChatView/logoBtn/index.jsx +103 -103
  16. package/src/YtChatView/logoSplitBtn/index.css +3 -3
  17. package/src/YtChatView/logoSplitBtn/index.jsx +105 -105
  18. package/src/YtChatView/mobileChat/index.jsx +945 -945
  19. package/src/YtChatView/mobileChat/index.module.css +253 -253
  20. package/src/YtChatView/previewDialog/index.jsx +601 -601
  21. package/src/YtChatView/previewDialog/index.module.css +253 -253
  22. package/src/chatWidget/chatWindow/index.tsx +426 -426
  23. package/src/chatWidget/index.tsx +2195 -2195
  24. package/src/index.tsx +127 -11
  25. package/webpack.config.js +50 -50
  26. package/.idea/sonarlint/issuestore/7/0/7030d0b2f71b999ff89a343de08c414af32fc93a +0 -0
  27. package/.idea/sonarlint/issuestore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d +0 -0
  28. package/.idea/sonarlint/issuestore/9/c/9cfff9a6d27bd6c255aa751213163c7901fb8ce7 +0 -0
  29. package/build/asset-manifest.json +0 -19
  30. package/build/index.html +0 -1
  31. package/build/static/css/main.8ee59d98.css +0 -2
  32. package/build/static/css/main.8ee59d98.css.map +0 -1
  33. package/build/static/js/main.ae39ed55.js +0 -3
  34. package/build/static/js/main.ae39ed55.js.LICENSE.txt +0 -181
  35. package/build/static/js/main.ae39ed55.js.map +0 -1
  36. package/build/static/media/aiavatar.74bafa995cce4c01b804.png +0 -0
  37. package/build/static/media/history-list-empty.1eb65b1550aef4e8c8a4.png +0 -0
  38. package/build/static/media/icon_history_headerbg.50747e81d01257f55346.png +0 -0
  39. package/build/static/media/moreAi.285e66289f838072060c.png +0 -0
  40. package/build/static/media/moreBg.9fc998472925cecd89f2.png +0 -0
  41. package/build/static/media/phone.19bc6f0d2e9eae4863ae.png +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
+ }