@clikvn/agent-widget-embedded 0.0.4-dev → 0.0.6-dev
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/Chat/AudioPlayer.d.ts +6 -0
- package/dist/components/Chat/AudioPlayer.d.ts.map +1 -0
- package/dist/components/Chat/Chat.d.ts.map +1 -1
- package/dist/components/Chat/Icons.d.ts +5 -2
- package/dist/components/Chat/Icons.d.ts.map +1 -1
- package/dist/components/Chat/Message.d.ts +1 -0
- package/dist/components/Chat/Message.d.ts.map +1 -1
- package/dist/components/Chat/MultimodalInput.d.ts +2 -0
- package/dist/components/Chat/MultimodalInput.d.ts.map +1 -1
- package/dist/features/AgentWidget/index.d.ts +2 -0
- package/dist/features/AgentWidget/index.d.ts.map +1 -1
- package/dist/hooks/useAudioRecording.d.ts +2 -6
- package/dist/hooks/useAudioRecording.d.ts.map +1 -1
- package/dist/hooks/useChat.d.ts +2 -0
- package/dist/hooks/useChat.d.ts.map +1 -1
- package/dist/hooks/useChatData.d.ts +2 -0
- package/dist/hooks/useChatData.d.ts.map +1 -1
- package/dist/hooks/useConfiguration.d.ts +1 -6
- package/dist/hooks/useConfiguration.d.ts.map +1 -1
- package/dist/index.html +12 -3
- package/dist/register.d.ts +5 -3
- package/dist/register.d.ts.map +1 -1
- package/dist/types/common.type.d.ts +5 -0
- package/dist/types/common.type.d.ts.map +1 -1
- package/dist/types/flowise.type.d.ts +2 -0
- package/dist/types/flowise.type.d.ts.map +1 -1
- package/dist/web.d.ts +1 -12
- package/dist/web.d.ts.map +1 -1
- package/dist/web.js +1 -1
- package/dist/window.d.ts +3 -15
- package/dist/window.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Chat/AudioPlayer.tsx +44 -0
- package/src/components/Chat/Chat.tsx +5 -0
- package/src/components/Chat/Icons.tsx +32 -2
- package/src/components/Chat/Message.tsx +6 -0
- package/src/components/Chat/MultimodalInput.tsx +56 -54
- package/src/features/AgentWidget/index.tsx +5 -2
- package/src/hooks/useAudioRecording.ts +4 -8
- package/src/hooks/useChat.ts +12 -2
- package/src/hooks/useChatData.tsx +3 -0
- package/src/hooks/useConfiguration.tsx +1 -6
- package/src/register.tsx +5 -2
- package/src/types/common.type.ts +6 -0
- package/src/types/flowise.type.ts +2 -0
- package/src/window.ts +2 -15
package/dist/window.d.ts
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
apiHost: string;
|
|
4
|
-
agentId: string;
|
|
5
|
-
overrideConfig?: {
|
|
6
|
-
chatId?: string | undefined;
|
|
7
|
-
overrideConfig?: Record<string, any>;
|
|
8
|
-
} & Record<string, unknown>;
|
|
9
|
-
theme?: {
|
|
10
|
-
avatar?: string;
|
|
11
|
-
} & Record<string, unknown>;
|
|
12
|
-
listeners?: Record<EVENT_TYPE, (props: any) => void>;
|
|
13
|
-
};
|
|
14
|
-
export declare const initWidget: (props: VoiceAgentWidget & {
|
|
1
|
+
import { AgentWidgetType } from './register';
|
|
2
|
+
export declare const initWidget: (props: AgentWidgetType & {
|
|
15
3
|
id?: string;
|
|
16
4
|
}) => void;
|
|
17
5
|
export declare const destroy: () => void;
|
|
@@ -20,7 +8,7 @@ type AgentWidget = {
|
|
|
20
8
|
destroy: typeof destroy;
|
|
21
9
|
};
|
|
22
10
|
export declare const parseAgentVoice: () => {
|
|
23
|
-
initWidget: (props:
|
|
11
|
+
initWidget: (props: AgentWidgetType & {
|
|
24
12
|
id?: string;
|
|
25
13
|
}) => void;
|
|
26
14
|
destroy: () => void;
|
package/dist/window.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../src/window.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../src/window.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAyB,MAAM,YAAY,CAAC;AAIpE,eAAO,MAAM,UAAU,UAAW,eAAe,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,SAYlE,CAAC;AAEF,eAAO,MAAM,OAAO,YAEnB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,OAAO,EAAE,OAAO,OAAO,CAAC;CACzB,CAAC;AAQF,eAAO,MAAM,eAAe;wBA7BM,eAAe,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE;;CAgCjE,CAAC;AAEH,eAAO,MAAM,wBAAwB,UAAW,WAAW,SAG1D,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
|
+
import { PlayIcon, StopIcon1 } from './Icons';
|
|
3
|
+
|
|
4
|
+
const AudioPlayer = ({
|
|
5
|
+
src,
|
|
6
|
+
autoplay = false,
|
|
7
|
+
}: {
|
|
8
|
+
src: string;
|
|
9
|
+
autoplay?: boolean;
|
|
10
|
+
}) => {
|
|
11
|
+
const audioRef = useRef<any>(null);
|
|
12
|
+
const [isPlaying, setIsPlaying] = useState(false);
|
|
13
|
+
|
|
14
|
+
const handlePlayPause = (e: any) => {
|
|
15
|
+
e.preventDefault();
|
|
16
|
+
if (isPlaying) {
|
|
17
|
+
audioRef.current.pause();
|
|
18
|
+
} else {
|
|
19
|
+
audioRef.current.play();
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
<button
|
|
26
|
+
className="rounded-full cursor-pointer h-fit w-[24px]"
|
|
27
|
+
onClick={handlePlayPause}
|
|
28
|
+
>
|
|
29
|
+
{isPlaying ? <StopIcon1 /> : <PlayIcon />}
|
|
30
|
+
</button>
|
|
31
|
+
<audio
|
|
32
|
+
ref={audioRef}
|
|
33
|
+
className="hidden"
|
|
34
|
+
src={src}
|
|
35
|
+
autoPlay={autoplay}
|
|
36
|
+
onEnded={() => setIsPlaying(false)}
|
|
37
|
+
onPause={() => setIsPlaying(false)}
|
|
38
|
+
onPlay={() => setIsPlaying(true)}
|
|
39
|
+
></audio>
|
|
40
|
+
</>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default AudioPlayer;
|
|
@@ -25,6 +25,8 @@ export const Chat: FC<PropsType> = ({ id, agentId, initialMessages = [] }) => {
|
|
|
25
25
|
chatId,
|
|
26
26
|
append,
|
|
27
27
|
bot,
|
|
28
|
+
enableTTS,
|
|
29
|
+
setEnableTTS,
|
|
28
30
|
} = useChat({ id, initialMessages, agentId });
|
|
29
31
|
const { apiHost } = useConfiguration();
|
|
30
32
|
const [messagesContainerRef, messagesEndRef] =
|
|
@@ -47,6 +49,7 @@ export const Chat: FC<PropsType> = ({ id, agentId, initialMessages = [] }) => {
|
|
|
47
49
|
chatId={id}
|
|
48
50
|
message={message}
|
|
49
51
|
isLoading={isLoading && (messages || []).length - 1 === index}
|
|
52
|
+
enableTTS={enableTTS}
|
|
50
53
|
/>
|
|
51
54
|
))}
|
|
52
55
|
|
|
@@ -76,6 +79,8 @@ export const Chat: FC<PropsType> = ({ id, agentId, initialMessages = [] }) => {
|
|
|
76
79
|
setAttachments={setAttachments}
|
|
77
80
|
bot={bot}
|
|
78
81
|
apiHost={apiHost}
|
|
82
|
+
setEnableTTS={setEnableTTS}
|
|
83
|
+
enableTTS={enableTTS}
|
|
79
84
|
/>
|
|
80
85
|
</form>
|
|
81
86
|
</div>
|
|
@@ -477,7 +477,13 @@ export const MoreIcon = ({ size = 16 }: { size?: number }) => {
|
|
|
477
477
|
);
|
|
478
478
|
};
|
|
479
479
|
|
|
480
|
-
export const TrashIcon = ({
|
|
480
|
+
export const TrashIcon = ({
|
|
481
|
+
size = 16,
|
|
482
|
+
color,
|
|
483
|
+
}: {
|
|
484
|
+
size?: number;
|
|
485
|
+
color?: string;
|
|
486
|
+
}) => {
|
|
481
487
|
return (
|
|
482
488
|
<svg
|
|
483
489
|
height={size}
|
|
@@ -882,7 +888,13 @@ export const MicrophoneIcon = ({ size = 16 }: { size?: number }) => {
|
|
|
882
888
|
);
|
|
883
889
|
};
|
|
884
890
|
|
|
885
|
-
export const CircleDotIcon = ({
|
|
891
|
+
export const CircleDotIcon = ({
|
|
892
|
+
size = 16,
|
|
893
|
+
color = 'red',
|
|
894
|
+
}: {
|
|
895
|
+
size?: number;
|
|
896
|
+
color?: string;
|
|
897
|
+
}) => (
|
|
886
898
|
<svg
|
|
887
899
|
xmlns="http://www.w3.org/2000/svg"
|
|
888
900
|
height={size}
|
|
@@ -898,3 +910,21 @@ export const CircleDotIcon = ({ size = 16, color = 'red' }: { size?: number, col
|
|
|
898
910
|
<circle cx="12" cy="12" r="1" />
|
|
899
911
|
</svg>
|
|
900
912
|
);
|
|
913
|
+
|
|
914
|
+
export const PlayIcon = () => (
|
|
915
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
|
916
|
+
<path d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zM188.3 147.1c7.6-4.2 16.8-4.1 24.3 .5l144 88c7.1 4.4 11.5 12.1 11.5 20.5s-4.4 16.1-11.5 20.5l-144 88c-7.4 4.5-16.7 4.7-24.3 .5s-12.3-12.2-12.3-20.9l0-176c0-8.7 4.7-16.7 12.3-20.9z" />
|
|
917
|
+
</svg>
|
|
918
|
+
);
|
|
919
|
+
|
|
920
|
+
export const StopIcon1 = () => (
|
|
921
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
|
922
|
+
<path d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm192-96l128 0c17.7 0 32 14.3 32 32l0 128c0 17.7-14.3 32-32 32l-128 0c-17.7 0-32-14.3-32-32l0-128c0-17.7 14.3-32 32-32z" />
|
|
923
|
+
</svg>
|
|
924
|
+
);
|
|
925
|
+
|
|
926
|
+
export const VolumeIcon = () => (
|
|
927
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
|
|
928
|
+
<path d="M533.6 32.5C598.5 85.2 640 165.8 640 256s-41.5 170.7-106.4 223.5c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C557.5 398.2 592 331.2 592 256s-34.5-142.2-88.7-186.3c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zM473.1 107c43.2 35.2 70.9 88.9 70.9 149s-27.7 113.8-70.9 149c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C475.3 341.3 496 301.1 496 256s-20.7-85.3-53.2-111.8c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zm-60.5 74.5C434.1 199.1 448 225.9 448 256s-13.9 56.9-35.4 74.5c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C393.1 284.4 400 271 400 256s-6.9-28.4-17.7-37.3c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zM301.1 34.8C312.6 40 320 51.4 320 64l0 384c0 12.6-7.4 24-18.9 29.2s-25 3.1-34.4-5.3L131.8 352 64 352c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l67.8 0L266.7 40.1c9.4-8.4 22.9-10.4 34.4-5.3z" />
|
|
929
|
+
</svg>
|
|
930
|
+
);
|
|
@@ -10,12 +10,14 @@ import {
|
|
|
10
10
|
ToolUsage,
|
|
11
11
|
} from '../../types/flowise.type';
|
|
12
12
|
import { cn } from '../../utils/commonUtils';
|
|
13
|
+
import AudioPlayer from './AudioPlayer';
|
|
13
14
|
|
|
14
15
|
type PropsType = {
|
|
15
16
|
chatId?: string;
|
|
16
17
|
message: ChatMessageType;
|
|
17
18
|
isLoading: boolean;
|
|
18
19
|
bot: BotType | null;
|
|
20
|
+
enableTTS?: boolean;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
const getRole = (role?: MessageRoleType) => {
|
|
@@ -31,6 +33,7 @@ export const PreviewMessage: FC<PropsType> = ({
|
|
|
31
33
|
message,
|
|
32
34
|
isLoading,
|
|
33
35
|
bot,
|
|
36
|
+
enableTTS,
|
|
34
37
|
}) => {
|
|
35
38
|
const parseOutput = (outputData: any) => {
|
|
36
39
|
try {
|
|
@@ -136,6 +139,9 @@ export const PreviewMessage: FC<PropsType> = ({
|
|
|
136
139
|
</Markdown>
|
|
137
140
|
</div>
|
|
138
141
|
)}
|
|
142
|
+
{message?.ttsUrl && (
|
|
143
|
+
<AudioPlayer src={message.ttsUrl} autoplay={!!enableTTS} />
|
|
144
|
+
)}
|
|
139
145
|
</div>
|
|
140
146
|
</div>
|
|
141
147
|
</motion.div>
|
|
@@ -12,17 +12,16 @@ import {
|
|
|
12
12
|
cn,
|
|
13
13
|
generateExtendedFileName,
|
|
14
14
|
generateUUID,
|
|
15
|
-
sleep,
|
|
16
15
|
} from '../../utils/commonUtils';
|
|
17
16
|
import { PreviewAttachment } from './PreviewAttachment';
|
|
18
17
|
import {
|
|
19
18
|
ArrowUpIcon,
|
|
20
19
|
CircleDotIcon,
|
|
21
20
|
MicrophoneIcon,
|
|
22
|
-
PaperclipIcon,
|
|
23
21
|
PlusIcon,
|
|
24
22
|
StopIcon,
|
|
25
23
|
TrashIcon,
|
|
24
|
+
VolumeIcon,
|
|
26
25
|
} from './Icons';
|
|
27
26
|
import { ChatMessageType, IFileUpload } from '../../types/flowise.type';
|
|
28
27
|
import { BotType } from '../../types/bot.type';
|
|
@@ -31,29 +30,7 @@ import { createAttachments } from '../../services/chat.service';
|
|
|
31
30
|
import { Button } from './ui/Button';
|
|
32
31
|
import { Textarea } from './ui/Textarea';
|
|
33
32
|
import { useAudioRecording } from '../../hooks/useAudioRecording';
|
|
34
|
-
|
|
35
|
-
const suggestedActions = [
|
|
36
|
-
{
|
|
37
|
-
title: 'What is the weather',
|
|
38
|
-
label: 'in Ha Noi?',
|
|
39
|
-
action: 'What is the weather in Ha Noi?',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
title: 'Create a travel plan for an traveling',
|
|
43
|
-
label: 'to Ha Noi',
|
|
44
|
-
action: 'Create a travel plan for an traveling to Ha Noi',
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
title: 'Top of tourist attractions',
|
|
48
|
-
label: 'in Ha Noi',
|
|
49
|
-
action: 'Top of tourist attractions in Ha Noi',
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
title: 'List of museums',
|
|
53
|
-
label: 'in Ha Noi',
|
|
54
|
-
action: 'List of museums in Ha Noi',
|
|
55
|
-
},
|
|
56
|
-
];
|
|
33
|
+
import { useChatData } from '../../hooks/useChatData';
|
|
57
34
|
|
|
58
35
|
type PropsType = {
|
|
59
36
|
input: string;
|
|
@@ -73,6 +50,8 @@ type PropsType = {
|
|
|
73
50
|
setAttachments?: (func: (files: IFileUpload[]) => IFileUpload[]) => void;
|
|
74
51
|
bot: BotType | null;
|
|
75
52
|
apiHost: string;
|
|
53
|
+
setEnableTTS: (value: boolean) => void;
|
|
54
|
+
enableTTS: boolean;
|
|
76
55
|
};
|
|
77
56
|
|
|
78
57
|
export const MultimodalInput: FC<PropsType> = ({
|
|
@@ -90,7 +69,10 @@ export const MultimodalInput: FC<PropsType> = ({
|
|
|
90
69
|
setAttachments,
|
|
91
70
|
bot,
|
|
92
71
|
apiHost,
|
|
72
|
+
setEnableTTS,
|
|
73
|
+
enableTTS,
|
|
93
74
|
}) => {
|
|
75
|
+
const { suggestedActions = [] } = useChatData();
|
|
94
76
|
const {
|
|
95
77
|
isRecording,
|
|
96
78
|
setIsRecording,
|
|
@@ -98,17 +80,7 @@ export const MultimodalInput: FC<PropsType> = ({
|
|
|
98
80
|
onRecordingStopped,
|
|
99
81
|
elapsedTime,
|
|
100
82
|
isLoadingRecording,
|
|
101
|
-
} = useAudioRecording(
|
|
102
|
-
addRecordingToPreviews: async (blob: Blob) => {
|
|
103
|
-
try {
|
|
104
|
-
const audioFile = await toAudioBase64(blob);
|
|
105
|
-
handleSubmit(undefined, [audioFile]);
|
|
106
|
-
setIsRecording(false);
|
|
107
|
-
} catch (error) {
|
|
108
|
-
console.error('Error uploading files!', error);
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
});
|
|
83
|
+
} = useAudioRecording();
|
|
112
84
|
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
|
|
113
85
|
const { width } = useWindowSize();
|
|
114
86
|
useEffect(() => {
|
|
@@ -289,6 +261,27 @@ export const MultimodalInput: FC<PropsType> = ({
|
|
|
289
261
|
[setAttachments, checkUploadFile]
|
|
290
262
|
);
|
|
291
263
|
|
|
264
|
+
const handleSubmitRecording = useCallback(
|
|
265
|
+
async (blob: Blob) => {
|
|
266
|
+
try {
|
|
267
|
+
const audioFile = await toAudioBase64(blob);
|
|
268
|
+
handleSubmit(undefined, [audioFile]);
|
|
269
|
+
setIsRecording(false);
|
|
270
|
+
} catch (error) {
|
|
271
|
+
console.error('Error uploading files!', error);
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
[handleSubmit, setIsRecording]
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
const handleSend = useCallback(async () => {
|
|
278
|
+
if (isRecording) {
|
|
279
|
+
onRecordingStopped(handleSubmitRecording);
|
|
280
|
+
} else {
|
|
281
|
+
submitForm();
|
|
282
|
+
}
|
|
283
|
+
}, [submitForm, onRecordingStopped, handleSubmitRecording]);
|
|
284
|
+
|
|
292
285
|
return (
|
|
293
286
|
<div className="relative w-full flex flex-col gap-4">
|
|
294
287
|
{messages.length === 0 && (
|
|
@@ -371,7 +364,6 @@ export const MultimodalInput: FC<PropsType> = ({
|
|
|
371
364
|
onKeyDown={(event) => {
|
|
372
365
|
if (event.key === 'Enter' && !event.shiftKey) {
|
|
373
366
|
event.preventDefault();
|
|
374
|
-
|
|
375
367
|
if (isLoading) {
|
|
376
368
|
console.error(
|
|
377
369
|
'Please wait for the model to finish its response!'
|
|
@@ -379,7 +371,7 @@ export const MultimodalInput: FC<PropsType> = ({
|
|
|
379
371
|
} else if (uploadQueue.length) {
|
|
380
372
|
console.error('Please wait for file is uploading!');
|
|
381
373
|
} else {
|
|
382
|
-
|
|
374
|
+
handleSend();
|
|
383
375
|
}
|
|
384
376
|
}
|
|
385
377
|
}}
|
|
@@ -401,11 +393,7 @@ export const MultimodalInput: FC<PropsType> = ({
|
|
|
401
393
|
className="rounded-full p-1.5 h-fit absolute bottom-2 right-2 m-0.5 border dark:border-zinc-600"
|
|
402
394
|
onClick={(event) => {
|
|
403
395
|
event.preventDefault();
|
|
404
|
-
|
|
405
|
-
onRecordingStopped();
|
|
406
|
-
} else {
|
|
407
|
-
submitForm();
|
|
408
|
-
}
|
|
396
|
+
handleSend();
|
|
409
397
|
}}
|
|
410
398
|
disabled={
|
|
411
399
|
!isRecording && (input.length === 0 || !!uploadQueue.length)
|
|
@@ -440,18 +428,32 @@ export const MultimodalInput: FC<PropsType> = ({
|
|
|
440
428
|
</Button>
|
|
441
429
|
</>
|
|
442
430
|
) : (
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
event
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
431
|
+
<>
|
|
432
|
+
<Button
|
|
433
|
+
className="rounded-full p-1.5 h-fit absolute bottom-2 right-11 m-0.5 dark:border-zinc-700"
|
|
434
|
+
onClick={(event) => {
|
|
435
|
+
event.preventDefault();
|
|
436
|
+
setIsRecording(true);
|
|
437
|
+
}}
|
|
438
|
+
variant="outline"
|
|
439
|
+
disabled={isLoading}
|
|
440
|
+
>
|
|
441
|
+
<MicrophoneIcon size={14} />
|
|
442
|
+
</Button>
|
|
443
|
+
<Button
|
|
444
|
+
className={`rounded-full p-1.5 h-fit absolute bottom-2 right-[80px] m-0.5 dark:border-zinc-700 ${enableTTS ? 'text-white hover:bg-primary/90 bg-primary' : ''}`}
|
|
445
|
+
onClick={(event) => {
|
|
446
|
+
event.preventDefault();
|
|
447
|
+
setEnableTTS(!enableTTS);
|
|
448
|
+
}}
|
|
449
|
+
variant="outline"
|
|
450
|
+
disabled={isLoading}
|
|
451
|
+
>
|
|
452
|
+
<VolumeIcon />
|
|
453
|
+
</Button>
|
|
454
|
+
</>
|
|
454
455
|
)}
|
|
456
|
+
|
|
455
457
|
<Button
|
|
456
458
|
className="rounded-full p-1.5 h-fit absolute bottom-2 left-2 m-0.5 dark:border-zinc-700"
|
|
457
459
|
onClick={(event) => {
|
|
@@ -5,6 +5,7 @@ import Agent from '../../components/Agent';
|
|
|
5
5
|
import { ChatDataProvider } from '../../hooks/useChatData';
|
|
6
6
|
import styles from '../../assets/tailwindcss.css';
|
|
7
7
|
import commonStyles from '../../assets/common.css';
|
|
8
|
+
import { SuggestionType } from '../../types/common.type';
|
|
8
9
|
|
|
9
10
|
export type AgentWidgetType = {
|
|
10
11
|
apiHost: string;
|
|
@@ -12,6 +13,7 @@ export type AgentWidgetType = {
|
|
|
12
13
|
overrideConfig?: {
|
|
13
14
|
chatId?: string | undefined;
|
|
14
15
|
overrideConfig?: Record<string, unknown>;
|
|
16
|
+
suggestedActions?: SuggestionType[];
|
|
15
17
|
} & Record<string, unknown>;
|
|
16
18
|
theme?: {
|
|
17
19
|
avatar?: string;
|
|
@@ -27,14 +29,15 @@ const AgentWidget: FC<AgentWidgetType> = (props: AgentWidgetType) => {
|
|
|
27
29
|
config={{
|
|
28
30
|
apiHost: props.apiHost,
|
|
29
31
|
agentId: props.agentId,
|
|
30
|
-
|
|
31
|
-
overrideConfig: props.overrideConfig,
|
|
32
|
+
overrideConfig: props.overrideConfig?.overrideConfig,
|
|
32
33
|
theme: props.theme,
|
|
33
34
|
}}
|
|
34
35
|
>
|
|
35
36
|
<ChatDataProvider
|
|
36
37
|
data={{
|
|
37
38
|
chatId: props.overrideConfig?.chatId,
|
|
39
|
+
suggestedActions: props.overrideConfig?.suggestedActions,
|
|
40
|
+
listeners: props.listeners,
|
|
38
41
|
}}
|
|
39
42
|
>
|
|
40
43
|
<Agent />
|
|
@@ -5,12 +5,7 @@ import {
|
|
|
5
5
|
stopAudioRecording,
|
|
6
6
|
} from '../utils/audioRecording';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
addRecordingToPreviews: (blob: Blob) => void;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const useAudioRecording = (props: Props) => {
|
|
13
|
-
const { addRecordingToPreviews } = props;
|
|
8
|
+
export const useAudioRecording = () => {
|
|
14
9
|
const [elapsedTime, setElapsedTime] = useState('00:00');
|
|
15
10
|
const [recordingNotSupported, setRecordingNotSupported] = useState(false);
|
|
16
11
|
const [isLoadingRecording, setIsLoadingRecording] = useState(false);
|
|
@@ -23,6 +18,7 @@ export const useAudioRecording = (props: Props) => {
|
|
|
23
18
|
}, [isRecording]);
|
|
24
19
|
const onRecordingStarted = () => {
|
|
25
20
|
setIsRecording(true);
|
|
21
|
+
setIsLoadingRecording(false);
|
|
26
22
|
startAudioRecording(
|
|
27
23
|
setIsRecording,
|
|
28
24
|
setRecordingNotSupported,
|
|
@@ -36,9 +32,9 @@ export const useAudioRecording = (props: Props) => {
|
|
|
36
32
|
setRecordingNotSupported(false);
|
|
37
33
|
};
|
|
38
34
|
|
|
39
|
-
const onRecordingStopped = () => {
|
|
35
|
+
const onRecordingStopped = (onStop: null | ((blob: Blob) => void)) => {
|
|
40
36
|
setIsLoadingRecording(true);
|
|
41
|
-
stopAudioRecording(
|
|
37
|
+
stopAudioRecording(onStop);
|
|
42
38
|
};
|
|
43
39
|
|
|
44
40
|
return {
|
package/src/hooks/useChat.ts
CHANGED
|
@@ -33,6 +33,8 @@ type ReturnType = {
|
|
|
33
33
|
chatId: string;
|
|
34
34
|
append: (message: ChatMessageType) => Promise<void>;
|
|
35
35
|
bot: BotType | null;
|
|
36
|
+
enableTTS: boolean;
|
|
37
|
+
setEnableTTS: (value: boolean) => void;
|
|
36
38
|
};
|
|
37
39
|
|
|
38
40
|
export const useChat = (props: PropsType): ReturnType => {
|
|
@@ -43,6 +45,7 @@ export const useChat = (props: PropsType): ReturnType => {
|
|
|
43
45
|
const chatIdRef = useRef<string>(idKey);
|
|
44
46
|
const [chatId, setChatId] = useState(idKey);
|
|
45
47
|
const [bot, setBot] = useState<BotType | null>(null);
|
|
48
|
+
const [enableTTS, setEnableTTS] = useState(false);
|
|
46
49
|
|
|
47
50
|
const updateChatId = (uuid: string) => {
|
|
48
51
|
chatIdRef.current = uuid;
|
|
@@ -91,6 +94,9 @@ export const useChat = (props: PropsType): ReturnType => {
|
|
|
91
94
|
lastMsg.content = newMessage.metaData.question;
|
|
92
95
|
}
|
|
93
96
|
mutateMessages([...msgs, { ...newMessage }]);
|
|
97
|
+
} else if (chunk.event == 'audio') {
|
|
98
|
+
newMessage.ttsUrl = chunk.data as string;
|
|
99
|
+
mutateMessages([...msgs, { ...newMessage }]);
|
|
94
100
|
}
|
|
95
101
|
};
|
|
96
102
|
|
|
@@ -170,7 +176,8 @@ export const useChat = (props: PropsType): ReturnType => {
|
|
|
170
176
|
chatId: chatIdRef.current,
|
|
171
177
|
question: message.content,
|
|
172
178
|
chatflowId: bot?.id,
|
|
173
|
-
overrideConfig: overrideConfig
|
|
179
|
+
overrideConfig: overrideConfig,
|
|
180
|
+
tts: enableTTS,
|
|
174
181
|
});
|
|
175
182
|
setInput('');
|
|
176
183
|
};
|
|
@@ -213,7 +220,8 @@ export const useChat = (props: PropsType): ReturnType => {
|
|
|
213
220
|
question: input || '',
|
|
214
221
|
uploads: files || [],
|
|
215
222
|
chatflowId: bot?.id,
|
|
216
|
-
overrideConfig: overrideConfig
|
|
223
|
+
overrideConfig: overrideConfig,
|
|
224
|
+
tts: enableTTS,
|
|
217
225
|
});
|
|
218
226
|
setInput('');
|
|
219
227
|
},
|
|
@@ -231,5 +239,7 @@ export const useChat = (props: PropsType): ReturnType => {
|
|
|
231
239
|
chatId,
|
|
232
240
|
append,
|
|
233
241
|
bot,
|
|
242
|
+
enableTTS,
|
|
243
|
+
setEnableTTS,
|
|
234
244
|
};
|
|
235
245
|
};
|
|
@@ -4,11 +4,13 @@ import { getChatMessage } from '../services/chat.service';
|
|
|
4
4
|
import { ChatMessageType } from '../types/flowise.type';
|
|
5
5
|
import { generateUUID } from '../utils/commonUtils';
|
|
6
6
|
import { useConfiguration } from './useConfiguration';
|
|
7
|
+
import { SuggestionType } from '../types/common.type';
|
|
7
8
|
|
|
8
9
|
type ChatData = {
|
|
9
10
|
chatId?: string | undefined;
|
|
10
11
|
listeners?: Record<EVENT_TYPE, (props: any) => void>;
|
|
11
12
|
initialMessages?: ChatMessageType[];
|
|
13
|
+
suggestedActions?: SuggestionType[];
|
|
12
14
|
};
|
|
13
15
|
|
|
14
16
|
const ChatDataContext = createContext<ChatData | undefined>(undefined);
|
|
@@ -21,6 +23,7 @@ export const ChatDataProvider = ({
|
|
|
21
23
|
data: ChatData;
|
|
22
24
|
}) => {
|
|
23
25
|
const [chatData, setChatData] = useState<ChatData>({
|
|
26
|
+
...data,
|
|
24
27
|
chatId: data.chatId || generateUUID(),
|
|
25
28
|
});
|
|
26
29
|
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import React, { createContext, useEffect, useState } from 'react';
|
|
2
|
-
import { EVENT_TYPE } from '../models';
|
|
3
2
|
|
|
4
3
|
type ConfigurationData = {
|
|
5
4
|
apiHost: string;
|
|
6
5
|
agentId: string;
|
|
7
|
-
overrideConfig?:
|
|
8
|
-
chatId?: string | undefined;
|
|
9
|
-
overrideConfig?: Record<string, any>;
|
|
10
|
-
} & Record<string, unknown>;
|
|
6
|
+
overrideConfig?: Record<string, any>;
|
|
11
7
|
theme?: {
|
|
12
8
|
avatar?: string;
|
|
13
9
|
} & Record<string, unknown>;
|
|
14
|
-
listeners?: Record<EVENT_TYPE, (props: any) => void>;
|
|
15
10
|
};
|
|
16
11
|
|
|
17
12
|
const ConfigurationContext = createContext<ConfigurationData | undefined>(
|
package/src/register.tsx
CHANGED
|
@@ -2,13 +2,15 @@ import { agentWidgetElementName } from './constants';
|
|
|
2
2
|
import * as ReactDom from 'react-dom';
|
|
3
3
|
import AgentWidget from './features/AgentWidget';
|
|
4
4
|
import { EVENT_TYPE } from './models';
|
|
5
|
+
import { SuggestionType } from './types/common.type';
|
|
5
6
|
|
|
6
|
-
type
|
|
7
|
+
export type AgentWidgetType = {
|
|
7
8
|
apiHost: string;
|
|
8
9
|
agentId: string;
|
|
9
10
|
overrideConfig?: {
|
|
10
11
|
chatId?: string | undefined;
|
|
11
12
|
overrideConfig?: Record<string, unknown>;
|
|
13
|
+
suggestedActions?: SuggestionType[];
|
|
12
14
|
} & Record<string, unknown>;
|
|
13
15
|
theme?: {
|
|
14
16
|
avatar?: string;
|
|
@@ -22,6 +24,7 @@ export class AgentWidgetComponent extends HTMLElement {
|
|
|
22
24
|
overrideConfig?: {
|
|
23
25
|
chatId?: string | undefined;
|
|
24
26
|
overrideConfig?: Record<string, unknown>;
|
|
27
|
+
suggestedActions?: SuggestionType[];
|
|
25
28
|
} & Record<string, unknown>;
|
|
26
29
|
theme?: {
|
|
27
30
|
avatar?: string;
|
|
@@ -32,7 +35,7 @@ export class AgentWidgetComponent extends HTMLElement {
|
|
|
32
35
|
this.updateAttributes = this.updateAttributes.bind(this);
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
updateAttributes(attributes:
|
|
38
|
+
updateAttributes(attributes: AgentWidgetType) {
|
|
36
39
|
this.apiHost = attributes.apiHost;
|
|
37
40
|
this.agentId = attributes.agentId;
|
|
38
41
|
this.overrideConfig = attributes.overrideConfig;
|
package/src/types/common.type.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface PredictionData {
|
|
|
11
11
|
leadEmail?: string;
|
|
12
12
|
action?: IAction;
|
|
13
13
|
language?: string;
|
|
14
|
+
tts?: boolean;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export interface ChatMessageType {
|
|
@@ -32,6 +33,7 @@ export interface ChatMessageType {
|
|
|
32
33
|
fileAnnotations?: FileAnnotation[];
|
|
33
34
|
agentReasoning?: AgentReasoning[];
|
|
34
35
|
metaData?: ChatMessageMetadataType;
|
|
36
|
+
ttsUrl?: string;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export interface ChatMessageMetadataType {
|
package/src/window.ts
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
import { agentWidgetElementName } from './constants';
|
|
2
|
-
import { registerWebComponents } from './register';
|
|
3
|
-
import { EVENT_TYPE } from './models';
|
|
2
|
+
import { AgentWidgetType, registerWebComponents } from './register';
|
|
4
3
|
|
|
5
4
|
let elementUsed: Element | undefined;
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
apiHost: string;
|
|
9
|
-
agentId: string;
|
|
10
|
-
overrideConfig?: {
|
|
11
|
-
chatId?: string | undefined;
|
|
12
|
-
overrideConfig?: Record<string, any>;
|
|
13
|
-
} & Record<string, unknown>;
|
|
14
|
-
theme?: {
|
|
15
|
-
avatar?: string;
|
|
16
|
-
} & Record<string, unknown>;
|
|
17
|
-
listeners?: Record<EVENT_TYPE, (props: any) => void>;
|
|
18
|
-
};
|
|
19
|
-
export const initWidget = (props: VoiceAgentWidget & { id?: string }) => {
|
|
6
|
+
export const initWidget = (props: AgentWidgetType & { id?: string }) => {
|
|
20
7
|
destroy();
|
|
21
8
|
const element: any = props.id
|
|
22
9
|
? document.getElementById(props.id)
|