@clikvn/agent-widget-embedded 0.0.9-dev → 0.0.10-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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@clikvn/agent-widget-embedded",
3
3
  "description": "This is agent widget",
4
- "version": "0.0.9-dev",
4
+ "version": "0.0.10-dev",
5
5
  "author": "Clik JSC",
6
6
  "license": "ISC",
7
7
  "type": "module",
@@ -27,6 +27,7 @@ export const Chat: FC<PropsType> = ({ id, agentId, initialMessages = [] }) => {
27
27
  bot,
28
28
  enableTTS,
29
29
  setEnableTTS,
30
+ suggestions
30
31
  } = useChat({ id, initialMessages, agentId });
31
32
  const { apiHost } = useConfiguration();
32
33
  const [messagesContainerRef, messagesEndRef] =
@@ -81,6 +82,7 @@ export const Chat: FC<PropsType> = ({ id, agentId, initialMessages = [] }) => {
81
82
  apiHost={apiHost}
82
83
  setEnableTTS={setEnableTTS}
83
84
  enableTTS={enableTTS}
85
+ suggestedActions={suggestions}
84
86
  />
85
87
  </form>
86
88
  </div>
@@ -32,6 +32,7 @@ import { Textarea } from './ui/Textarea';
32
32
  import { useAudioRecording } from '../../hooks/useAudioRecording';
33
33
  import { useChatData } from '../../hooks/useChatData';
34
34
  import { useConfiguration } from '../../hooks/useConfiguration';
35
+ import { SuggestionType } from 'types/common.type';
35
36
 
36
37
  type PropsType = {
37
38
  input: string;
@@ -53,6 +54,7 @@ type PropsType = {
53
54
  apiHost: string;
54
55
  setEnableTTS: (value: boolean) => void;
55
56
  enableTTS: boolean;
57
+ suggestedActions?: SuggestionType[];
56
58
  };
57
59
 
58
60
  export const MultimodalInput: FC<PropsType> = ({
@@ -72,9 +74,9 @@ export const MultimodalInput: FC<PropsType> = ({
72
74
  apiHost,
73
75
  setEnableTTS,
74
76
  enableTTS,
77
+ suggestedActions,
75
78
  }) => {
76
79
  const { theme } = useConfiguration();
77
- const { suggestedActions = [] } = useChatData();
78
80
  const {
79
81
  isRecording,
80
82
  setIsRecording,
@@ -286,7 +288,7 @@ export const MultimodalInput: FC<PropsType> = ({
286
288
 
287
289
  return (
288
290
  <div className="relative w-full flex flex-col gap-4">
289
- {messages.length === 0 && (
291
+ {!!suggestedActions?.length && (
290
292
  <div className="grid sm:grid-cols-2 gap-2 w-full">
291
293
  {suggestedActions.map((suggestedAction, index) => (
292
294
  <motion.div
@@ -299,7 +301,8 @@ export const MultimodalInput: FC<PropsType> = ({
299
301
  >
300
302
  <Button
301
303
  variant="ghost"
302
- onClick={async () => {
304
+ onClick={(e) => {
305
+ e.preventDefault();
303
306
  if (append) {
304
307
  append({
305
308
  role: 'apiMessage',
@@ -309,10 +312,14 @@ export const MultimodalInput: FC<PropsType> = ({
309
312
  }}
310
313
  className="text-left border rounded-xl px-4 py-3.5 text-sm flex-1 gap-1 sm:flex-col w-full h-auto justify-start items-start"
311
314
  >
312
- <span className="font-medium">{suggestedAction.title}</span>
313
- <span className="text-muted-foreground">
314
- {suggestedAction.label}
315
+ <span className="font-medium overflow-hidden whitespace-nowrap text-ellipsis w-full group-hover:overflow-visible group-hover:whitespace-normal">
316
+ {suggestedAction.title}
315
317
  </span>
318
+ {!!suggestedAction.label && (
319
+ <span className="text-muted-foreground">
320
+ {suggestedAction.label}
321
+ </span>
322
+ )}
316
323
  </Button>
317
324
  </motion.div>
318
325
  ))}
@@ -1,7 +1,7 @@
1
1
  import useSWR from 'swr';
2
2
  import { useCallback, useEffect, useRef, useState } from 'react';
3
3
  import { StreamResponse } from '../models/FlowiseClient';
4
- import { predict } from '../services/chat.service';
4
+ import { getSuggestions, predict } from '../services/chat.service';
5
5
  import {
6
6
  ChatMessageMetadataType,
7
7
  ChatMessageType,
@@ -14,6 +14,7 @@ import { generateUUID } from '../utils/commonUtils';
14
14
  import { getBot } from '../services/bot.service';
15
15
  import { BotType } from '../types/bot.type';
16
16
  import { useConfiguration } from './useConfiguration';
17
+ import { SuggestionType } from 'types/common.type';
17
18
 
18
19
  type PropsType = {
19
20
  id?: string;
@@ -35,17 +36,20 @@ type ReturnType = {
35
36
  bot: BotType | null;
36
37
  enableTTS: boolean;
37
38
  setEnableTTS: (value: boolean) => void;
39
+ suggestions: SuggestionType[]
38
40
  };
39
41
 
40
42
  export const useChat = (props: PropsType): ReturnType => {
41
43
  const { id, initialMessages, initialInput, agentId } = props;
42
- const { apiHost, overrideConfig } = useConfiguration();
44
+ const { apiHost, overrideConfig, theme } = useConfiguration();
43
45
 
44
46
  const idKey = id ?? generateUUID();
45
47
  const chatIdRef = useRef<string>(idKey);
46
48
  const [chatId, setChatId] = useState(idKey);
47
49
  const [bot, setBot] = useState<BotType | null>(null);
48
50
  const [enableTTS, setEnableTTS] = useState(false);
51
+ const [suggestions, setSuggestions] = useState<SuggestionType[]>([]);
52
+
49
53
 
50
54
  const updateChatId = (uuid: string) => {
51
55
  chatIdRef.current = uuid;
@@ -62,6 +66,17 @@ export const useChat = (props: PropsType): ReturnType => {
62
66
  getBot(agentId || 'default', apiHost).then((res) => setBot(res));
63
67
  }, [agentId, apiHost]);
64
68
 
69
+ useEffect(() => {
70
+ if (bot?.id && chatId) {
71
+ updateSuggestions(`Agent name: ${bot.name}, Title: ${theme?.overview?.title}`)
72
+ }
73
+ }, [bot?.id, chatId])
74
+
75
+ const updateSuggestions = useCallback(async (question?: string) => {
76
+ const resSuggestions = await getSuggestions({ id: chatId, question, apiHost });
77
+ setSuggestions(resSuggestions);
78
+ }, [setSuggestions, chatId]);
79
+
65
80
  const processResponseStream = async (
66
81
  msgs: ChatMessageType[],
67
82
  req: PredictionData
@@ -94,6 +109,7 @@ export const useChat = (props: PropsType): ReturnType => {
94
109
  lastMsg.content = newMessage.metaData.question;
95
110
  }
96
111
  mutateMessages([...msgs, { ...newMessage }]);
112
+ updateSuggestions(`Agent name: ${bot?.name}, Title: ${theme?.overview?.title}`);
97
113
  } else if (chunk.event == 'audio') {
98
114
  newMessage.ttsUrl = chunk.data as string;
99
115
  mutateMessages([...msgs, { ...newMessage }]);
@@ -241,5 +257,6 @@ export const useChat = (props: PropsType): ReturnType => {
241
257
  bot,
242
258
  enableTTS,
243
259
  setEnableTTS,
260
+ suggestions
244
261
  };
245
262
  };
@@ -8,3 +8,5 @@ export const API_PREDICTION = `${API_CHATS}/prediction`;
8
8
  export const API_CHATBOTS = `${API_VERSION}/bots`;
9
9
 
10
10
  export const API_CREATE_ATTACHMENTS = `${API_CHATS}/attachments`;
11
+
12
+ export const API_SUGGESTIONS = `${API_CHATS}/suggestions`;
@@ -4,10 +4,11 @@ import {
4
4
  API_CHATS,
5
5
  API_CREATE_ATTACHMENTS,
6
6
  API_PREDICTION,
7
+ API_SUGGESTIONS,
7
8
  API_VERSION,
8
9
  } from './apis';
9
10
  import { ChatRequestType, ChatType } from '../types/chat.type';
10
- import { CommonChatType } from '../types/common.type';
11
+ import { CommonChatType, SuggestionType } from '../types/common.type';
11
12
  import {
12
13
  AttachmentUploadResult,
13
14
  ChatMessageType,
@@ -162,3 +163,37 @@ export const getById = async ({
162
163
  method: 'GET',
163
164
  });
164
165
  };
166
+
167
+ export const getSuggestions = async ({
168
+ accessToken,
169
+ id,
170
+ question,
171
+ apiHost
172
+ }: {
173
+ accessToken?: string;
174
+ id: string;
175
+ question?: string;
176
+ apiHost: string;
177
+ }): Promise<SuggestionType[]> => {
178
+ const headers = accessToken
179
+ ? {
180
+ Authorization: `Bearer ${accessToken}`,
181
+ 'Content-Type': 'application/json',
182
+ }
183
+ : {};
184
+ const url = accessToken
185
+ ? `${API_SUGGESTIONS}/${id}`
186
+ : `${API_VERSION}${API_SUGGESTIONS}/${id}`;
187
+ const req = {
188
+ question
189
+ }
190
+ const formData = new FormData();
191
+ formData.append('question', `${question}`);
192
+ return request({
193
+ host: apiHost,
194
+ url,
195
+ headers,
196
+ method: 'POST',
197
+ body: formData,
198
+ });
199
+ };