@clikvn/agent-widget-embedded 0.0.1-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.
Files changed (130) hide show
  1. package/.eslintrc +34 -0
  2. package/.prettierrc +8 -0
  3. package/README.md +20 -0
  4. package/base.json +21 -0
  5. package/dist/commons/constants/index.d.ts +2 -0
  6. package/dist/commons/constants/index.d.ts.map +1 -0
  7. package/dist/commons/constants/variables.d.ts +5 -0
  8. package/dist/commons/constants/variables.d.ts.map +1 -0
  9. package/dist/components/Agent/index.d.ts +3 -0
  10. package/dist/components/Agent/index.d.ts.map +1 -0
  11. package/dist/components/Chat/Chat.d.ts +10 -0
  12. package/dist/components/Chat/Chat.d.ts.map +1 -0
  13. package/dist/components/Chat/Icons.d.ts +120 -0
  14. package/dist/components/Chat/Icons.d.ts.map +1 -0
  15. package/dist/components/Chat/Markdown.d.ts +7 -0
  16. package/dist/components/Chat/Markdown.d.ts.map +1 -0
  17. package/dist/components/Chat/Message.d.ts +15 -0
  18. package/dist/components/Chat/Message.d.ts.map +1 -0
  19. package/dist/components/Chat/MultimodalInput.d.ts +24 -0
  20. package/dist/components/Chat/MultimodalInput.d.ts.map +1 -0
  21. package/dist/components/Chat/Overview.d.ts +8 -0
  22. package/dist/components/Chat/Overview.d.ts.map +1 -0
  23. package/dist/components/Chat/PreviewAttachment.d.ts +6 -0
  24. package/dist/components/Chat/PreviewAttachment.d.ts.map +1 -0
  25. package/dist/components/Chat/ui/Button.d.ts +12 -0
  26. package/dist/components/Chat/ui/Button.d.ts.map +1 -0
  27. package/dist/components/Chat/ui/Textarea.d.ts +6 -0
  28. package/dist/components/Chat/ui/Textarea.d.ts.map +1 -0
  29. package/dist/constants.d.ts +2 -0
  30. package/dist/constants.d.ts.map +1 -0
  31. package/dist/features/AgentWidget/index.d.ts +16 -0
  32. package/dist/features/AgentWidget/index.d.ts.map +1 -0
  33. package/dist/hooks/useChat.d.ts +25 -0
  34. package/dist/hooks/useChat.d.ts.map +1 -0
  35. package/dist/hooks/useChatData.d.ts +18 -0
  36. package/dist/hooks/useChatData.d.ts.map +1 -0
  37. package/dist/hooks/useConfiguration.d.ts +20 -0
  38. package/dist/hooks/useConfiguration.d.ts.map +1 -0
  39. package/dist/hooks/useConnection.d.ts +15 -0
  40. package/dist/hooks/useConnection.d.ts.map +1 -0
  41. package/dist/hooks/useScrollToBottom.d.ts +6 -0
  42. package/dist/hooks/useScrollToBottom.d.ts.map +1 -0
  43. package/dist/index.d.ts +2 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/models/FlowiseClient.d.ts +20 -0
  46. package/dist/models/FlowiseClient.d.ts.map +1 -0
  47. package/dist/models.d.ts +2 -0
  48. package/dist/models.d.ts.map +1 -0
  49. package/dist/register.d.ts +30 -0
  50. package/dist/register.d.ts.map +1 -0
  51. package/dist/services/apis.d.ts +7 -0
  52. package/dist/services/apis.d.ts.map +1 -0
  53. package/dist/services/bot.service.d.ts +3 -0
  54. package/dist/services/bot.service.d.ts.map +1 -0
  55. package/dist/services/chat.service.d.ts +32 -0
  56. package/dist/services/chat.service.d.ts.map +1 -0
  57. package/dist/services/user.service.d.ts +3 -0
  58. package/dist/services/user.service.d.ts.map +1 -0
  59. package/dist/types/agentType.d.ts +11 -0
  60. package/dist/types/agentType.d.ts.map +1 -0
  61. package/dist/types/bot.type.d.ts +11 -0
  62. package/dist/types/bot.type.d.ts.map +1 -0
  63. package/dist/types/chat.type.d.ts +10 -0
  64. package/dist/types/chat.type.d.ts.map +1 -0
  65. package/dist/types/common.type.d.ts +11 -0
  66. package/dist/types/common.type.d.ts.map +1 -0
  67. package/dist/types/flowise.type.d.ts +90 -0
  68. package/dist/types/flowise.type.d.ts.map +1 -0
  69. package/dist/types/user.type.d.ts +14 -0
  70. package/dist/types/user.type.d.ts.map +1 -0
  71. package/dist/types.d.ts +1 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/utils/commonUtils.d.ts +7 -0
  74. package/dist/utils/commonUtils.d.ts.map +1 -0
  75. package/dist/utils/functionUtils.d.ts +3 -0
  76. package/dist/utils/functionUtils.d.ts.map +1 -0
  77. package/dist/utils/requestUtils.d.ts +16 -0
  78. package/dist/utils/requestUtils.d.ts.map +1 -0
  79. package/dist/utils/streamUtils.d.ts +5 -0
  80. package/dist/utils/streamUtils.d.ts.map +1 -0
  81. package/dist/web.d.ts +18 -0
  82. package/dist/web.d.ts.map +1 -0
  83. package/dist/web.js +1 -0
  84. package/dist/window.d.ts +29 -0
  85. package/dist/window.d.ts.map +1 -0
  86. package/package.json +91 -0
  87. package/rollup.config.js +56 -0
  88. package/src/assets/common.css +148 -0
  89. package/src/assets/tailwindcss.css +3 -0
  90. package/src/commons/constants/index.ts +1 -0
  91. package/src/commons/constants/variables.ts +20 -0
  92. package/src/components/Agent/index.tsx +14 -0
  93. package/src/components/Chat/Chat.tsx +84 -0
  94. package/src/components/Chat/Icons.tsx +883 -0
  95. package/src/components/Chat/Markdown.tsx +324 -0
  96. package/src/components/Chat/Message.tsx +185 -0
  97. package/src/components/Chat/MultimodalInput.tsx +371 -0
  98. package/src/components/Chat/Overview.tsx +47 -0
  99. package/src/components/Chat/PreviewAttachment.tsx +41 -0
  100. package/src/components/Chat/ui/Button.tsx +55 -0
  101. package/src/components/Chat/ui/Textarea.tsx +23 -0
  102. package/src/constants.ts +1 -0
  103. package/src/env.d.ts +10 -0
  104. package/src/features/AgentWidget/index.tsx +47 -0
  105. package/src/global.d.ts +1 -0
  106. package/src/hooks/useChat.ts +225 -0
  107. package/src/hooks/useChatData.tsx +68 -0
  108. package/src/hooks/useConfiguration.tsx +54 -0
  109. package/src/hooks/useScrollToBottom.ts +31 -0
  110. package/src/index.ts +1 -0
  111. package/src/models/FlowiseClient.ts +103 -0
  112. package/src/models.ts +1 -0
  113. package/src/register.tsx +66 -0
  114. package/src/services/apis.ts +10 -0
  115. package/src/services/bot.service.ts +15 -0
  116. package/src/services/chat.service.ts +164 -0
  117. package/src/types/bot.type.ts +10 -0
  118. package/src/types/chat.type.ts +11 -0
  119. package/src/types/common.type.ts +11 -0
  120. package/src/types/flowise.type.ts +99 -0
  121. package/src/types/user.type.ts +15 -0
  122. package/src/types.ts +0 -0
  123. package/src/utils/commonUtils.ts +47 -0
  124. package/src/utils/functionUtils.ts +17 -0
  125. package/src/utils/requestUtils.ts +113 -0
  126. package/src/utils/streamUtils.ts +18 -0
  127. package/src/web.ts +6 -0
  128. package/src/window.ts +55 -0
  129. package/tailwind.config.cjs +122 -0
  130. package/tsconfig.json +24 -0
@@ -0,0 +1,225 @@
1
+ import useSWR from 'swr';
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
+ import { StreamResponse } from '../models/FlowiseClient';
4
+ import { predict } from '../services/chat.service';
5
+ import {
6
+ ChatMessageType,
7
+ IFileUpload,
8
+ PredictionData,
9
+ SourceDocument,
10
+ ToolUsage,
11
+ } from '../types/flowise.type';
12
+ import { generateUUID } from '../utils/commonUtils';
13
+ import { getBot } from '../services/bot.service';
14
+ import { BotType } from '../types/bot.type';
15
+ import { useConfiguration } from './useConfiguration';
16
+
17
+ type PropsType = {
18
+ id?: string;
19
+ agentId?: string;
20
+ initialMessages: ChatMessageType[];
21
+ initialInput?: string;
22
+ };
23
+
24
+ type ReturnType = {
25
+ messages?: ChatMessageType[];
26
+ setMessages: (messages: ChatMessageType[]) => void;
27
+ handleSubmit: (event?: { preventDefault?: () => void }) => void;
28
+ input?: string;
29
+ setInput: (input: string) => void;
30
+ isLoading: boolean;
31
+ stop: () => void;
32
+ chatId: string;
33
+ append: (message: ChatMessageType) => Promise<void>;
34
+ bot: BotType | null;
35
+ };
36
+
37
+ export const useChat = (props: PropsType): ReturnType => {
38
+ const { id, initialMessages, initialInput, agentId } = props;
39
+ const { apiHost } = useConfiguration();
40
+
41
+ const idKey = id ?? generateUUID();
42
+ const chatIdRef = useRef<string>(idKey);
43
+ const [chatId, setChatId] = useState(idKey);
44
+ const [bot, setBot] = useState<BotType | null>(null);
45
+
46
+ const updateChatId = (uuid: string) => {
47
+ chatIdRef.current = uuid;
48
+ setChatId(uuid);
49
+ };
50
+
51
+ useEffect(() => {
52
+ if (id) {
53
+ updateChatId(id);
54
+ }
55
+ }, [id]);
56
+
57
+ useEffect(() => {
58
+ getBot(agentId || 'default', apiHost).then((res) => setBot(res));
59
+ }, [agentId, apiHost]);
60
+
61
+ const processResponseStream = async (
62
+ msgs: ChatMessageType[],
63
+ req: PredictionData
64
+ ) => {
65
+ // Do an optimistic update to the chat state to show the updated messages immediately:
66
+ mutateMessages(msgs, false);
67
+
68
+ const newMessage: ChatMessageType = {
69
+ id: generateUUID(),
70
+ chatId: chatIdRef.current,
71
+ role: 'apiMessage',
72
+ content: '',
73
+ createdDate: new Date().toISOString(),
74
+ };
75
+
76
+ const onUpdate = (chunk: StreamResponse) => {
77
+ if (chunk?.event === 'token') {
78
+ newMessage.content = newMessage.content + (chunk.data as string);
79
+ mutateMessages([...msgs, { ...newMessage }]);
80
+ } else if (chunk.event == 'usedTools') {
81
+ newMessage.usedTools = chunk.data as ToolUsage[];
82
+ mutateMessages([...msgs, { ...newMessage }]);
83
+ } else if (chunk.event == 'sourceDocuments') {
84
+ newMessage.sourceDocuments = chunk.data as SourceDocument[];
85
+ mutateMessages([...msgs, { ...newMessage }]);
86
+ }
87
+ };
88
+
89
+ return await predict({
90
+ req,
91
+ apiHost,
92
+ onUpdate,
93
+ });
94
+ };
95
+
96
+ // Store a empty array as the initial messages
97
+ // (instead of using a default parameter value that gets re-created each time)
98
+ // to avoid re-renders:
99
+ const [initialMessagesFallback] = useState([]);
100
+
101
+ // Store the chat state in SWR, using the chatId as the key to share states.
102
+ const { data: messages, mutate: mutateMessages } = useSWR<ChatMessageType[]>(
103
+ [chatId, 'messages'],
104
+ null,
105
+ { fallbackData: initialMessages ?? initialMessagesFallback }
106
+ );
107
+
108
+ // Keep the latest messages in a ref.
109
+ const messagesRef = useRef<ChatMessageType[]>(messages || []);
110
+ useEffect(() => {
111
+ messagesRef.current = messages || [];
112
+ }, [messages]);
113
+
114
+ // We store loading state in another hook to sync loading states across hook invocations
115
+ const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(
116
+ [chatId, 'loading'],
117
+ null
118
+ );
119
+
120
+ // Abort controller to cancel the current API call.
121
+ const abortControllerRef = useRef<AbortController | null>(null);
122
+
123
+ const triggerRequest = useCallback(
124
+ async (msgs: ChatMessageType[], req: PredictionData) => {
125
+ try {
126
+ mutateLoading(true);
127
+
128
+ const abortController = new AbortController();
129
+ abortControllerRef.current = abortController;
130
+
131
+ await processResponseStream(msgs, req);
132
+
133
+ abortControllerRef.current = null;
134
+ } catch (err) {
135
+ // Ignore abort errors as they are expected.
136
+ if ((err as any).name === 'AbortError') {
137
+ abortControllerRef.current = null;
138
+ return null;
139
+ }
140
+
141
+ console.error(err);
142
+ } finally {
143
+ mutateLoading(false);
144
+ }
145
+ },
146
+ [mutateMessages, mutateLoading]
147
+ );
148
+
149
+ const append = async (message: ChatMessageType) => {
150
+ if (!message.content) {
151
+ return;
152
+ }
153
+ const msgs = messagesRef.current.concat({
154
+ id: generateUUID(),
155
+ chatId: chatIdRef.current,
156
+ role: 'userMessage',
157
+ content: message.content,
158
+ createdDate: new Date().toISOString(),
159
+ });
160
+
161
+ triggerRequest(msgs, {
162
+ chatId: chatIdRef.current,
163
+ question: message.content,
164
+ chatflowId: bot?.id,
165
+ });
166
+ setInput('');
167
+ };
168
+
169
+ const stop = useCallback(() => {
170
+ if (abortControllerRef.current) {
171
+ abortControllerRef.current?.abort();
172
+ abortControllerRef.current = null;
173
+ }
174
+ }, []);
175
+
176
+ const setMessages = useCallback(
177
+ (msgs: ChatMessageType[]) => {
178
+ mutateMessages(msgs, false);
179
+ messagesRef.current = msgs;
180
+ },
181
+ [mutateMessages]
182
+ );
183
+
184
+ // Input state and handlers.
185
+ const [input, setInput] = useState(initialInput);
186
+
187
+ const handleSubmit = useCallback(
188
+ async (event?: { preventDefault?: () => void }, files?: IFileUpload[]) => {
189
+ event?.preventDefault?.();
190
+
191
+ if (!input) return;
192
+
193
+ const msgs = messagesRef.current.concat({
194
+ id: generateUUID(),
195
+ chatId: chatIdRef.current,
196
+ role: 'userMessage',
197
+ content: input,
198
+ createdDate: new Date().toISOString(),
199
+ fileUploads: files || [],
200
+ });
201
+
202
+ triggerRequest(msgs, {
203
+ chatId: chatIdRef.current,
204
+ question: input,
205
+ uploads: files || [],
206
+ chatflowId: bot?.id,
207
+ });
208
+ setInput('');
209
+ },
210
+ [input, triggerRequest, bot]
211
+ );
212
+
213
+ return {
214
+ messages,
215
+ setMessages,
216
+ input,
217
+ setInput,
218
+ isLoading,
219
+ handleSubmit,
220
+ stop,
221
+ chatId,
222
+ append,
223
+ bot,
224
+ };
225
+ };
@@ -0,0 +1,68 @@
1
+ import React, { createContext, useEffect, useState } from 'react';
2
+ import { EVENT_TYPE } from '../models';
3
+ import { getChatMessage } from '../services/chat.service';
4
+ import { ChatMessageType } from '../types/flowise.type';
5
+ import { generateUUID } from '../utils/commonUtils';
6
+ import { useConfiguration } from './useConfiguration';
7
+
8
+ type ChatData = {
9
+ chatId?: string | undefined;
10
+ theme?: {
11
+ avatar?: string;
12
+ } & Record<string, unknown>;
13
+ listeners?: Record<EVENT_TYPE, (props: any) => void>;
14
+ initialMessages?: ChatMessageType[];
15
+ };
16
+
17
+ const ChatDataContext = createContext<ChatData | undefined>(undefined);
18
+
19
+ export const ChatDataProvider = ({
20
+ children,
21
+ data,
22
+ }: {
23
+ children: React.ReactNode;
24
+ data: ChatData;
25
+ }) => {
26
+ const [chatData, setChatData] = useState<ChatData>({
27
+ chatId: data.chatId || generateUUID(),
28
+ });
29
+
30
+ const { apiHost } = useConfiguration();
31
+
32
+ const fetchHistory = async () => {
33
+ if (!chatData?.chatId) {
34
+ return;
35
+ }
36
+
37
+ const initialMessages = await getChatMessage({
38
+ chatId: chatData.chatId!,
39
+ apiHost,
40
+ });
41
+ setChatData({
42
+ ...chatData,
43
+ initialMessages,
44
+ });
45
+ };
46
+
47
+ useEffect(() => {
48
+ setChatData({ ...data, chatId: chatData.chatId });
49
+ }, [data]);
50
+
51
+ useEffect(() => {
52
+ fetchHistory();
53
+ }, [chatData?.chatId]);
54
+
55
+ return (
56
+ <ChatDataContext.Provider value={chatData}>
57
+ {children}
58
+ </ChatDataContext.Provider>
59
+ );
60
+ };
61
+
62
+ export const useChatData = () => {
63
+ const context = React.useContext(ChatDataContext);
64
+ if (context === undefined) {
65
+ throw new Error('useChatData must be used within a ChatDataContext');
66
+ }
67
+ return context;
68
+ };
@@ -0,0 +1,54 @@
1
+ import React, { createContext, useEffect, useState } from 'react';
2
+ import { EVENT_TYPE } from '../models';
3
+
4
+ type ConfigurationData = {
5
+ apiHost: string;
6
+ agentId: string;
7
+ overrideConfig?: {
8
+ chatId?: string | undefined;
9
+ } & Record<string, unknown>;
10
+ theme?: {
11
+ avatar?: string;
12
+ } & Record<string, unknown>;
13
+ listeners?: Record<EVENT_TYPE, (props: any) => void>;
14
+ };
15
+
16
+ const ConfigurationContext = createContext<ConfigurationData | undefined>(
17
+ undefined
18
+ );
19
+
20
+ export const ConfigurationProvider = ({
21
+ children,
22
+ config,
23
+ }: {
24
+ children: React.ReactNode;
25
+ config: ConfigurationData;
26
+ }) => {
27
+ const [configuration, setConfiguration] = useState<ConfigurationData>({
28
+ apiHost: config.apiHost,
29
+ agentId: config.agentId,
30
+ });
31
+
32
+ useEffect(() => {
33
+ if (!config.apiHost) {
34
+ throw new Error('apiHost is required');
35
+ }
36
+ setConfiguration(config);
37
+ }, [config]);
38
+
39
+ return (
40
+ <ConfigurationContext.Provider value={configuration}>
41
+ {children}
42
+ </ConfigurationContext.Provider>
43
+ );
44
+ };
45
+
46
+ export const useConfiguration = () => {
47
+ const context = React.useContext(ConfigurationContext);
48
+ if (context === undefined) {
49
+ throw new Error(
50
+ 'useConfiguration must be used within a ConfigurationProvider'
51
+ );
52
+ }
53
+ return context;
54
+ };
@@ -0,0 +1,31 @@
1
+ import { type RefObject, useEffect, useRef } from 'react';
2
+
3
+ export function useScrollToBottom<T extends HTMLElement>(): [
4
+ RefObject<T>,
5
+ RefObject<T>,
6
+ ] {
7
+ const containerRef = useRef<T>(null);
8
+ const endRef = useRef<T>(null);
9
+
10
+ useEffect(() => {
11
+ const container = containerRef.current;
12
+ const end = endRef.current;
13
+
14
+ if (container && end) {
15
+ const observer = new MutationObserver(() => {
16
+ end.scrollIntoView({ behavior: 'instant', block: 'end' });
17
+ });
18
+
19
+ observer.observe(container, {
20
+ childList: true,
21
+ subtree: true,
22
+ attributes: true,
23
+ characterData: true,
24
+ });
25
+
26
+ return () => observer.disconnect();
27
+ }
28
+ }, []);
29
+
30
+ return [containerRef, endRef];
31
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export type { AgentWidgetType } from './features/AgentWidget';
@@ -0,0 +1,103 @@
1
+ import { PredictionData } from '../types/flowise.type';
2
+ import { BE_API, LANGUAGE_HEADER } from '../commons/constants';
3
+
4
+ interface FlowiseClientOptions {
5
+ baseUrl: string;
6
+ accessToken?: string;
7
+ host?: string;
8
+ }
9
+
10
+ export interface StreamResponse {
11
+ event: string;
12
+ data: unknown;
13
+ }
14
+
15
+ type PredictionResponse<T extends PredictionData> = T['streaming'] extends true
16
+ ? AsyncGenerator<StreamResponse, void, unknown> // Streaming returns an async generator
17
+ : Record<string, any>;
18
+
19
+ export default class FlowiseClient {
20
+ private baseUrl: string;
21
+ private accessToken: string | undefined;
22
+ private host: string | undefined;
23
+
24
+ constructor(options: FlowiseClientOptions) {
25
+ this.baseUrl = options.baseUrl;
26
+ this.accessToken = options.accessToken || '';
27
+ this.host = options.host || BE_API;
28
+ }
29
+
30
+ // Method to create a new prediction and handle streaming response
31
+ async createPrediction<T extends PredictionData>(
32
+ data: T
33
+ ): Promise<PredictionResponse<T>> {
34
+ const { chatId, streaming = true, language } = data;
35
+
36
+ const predictionUrl = `${this.host}${this.baseUrl}/${chatId}`;
37
+ let apiLanguage: string = LANGUAGE_HEADER.en;
38
+ if (language) {
39
+ apiLanguage = LANGUAGE_HEADER[language];
40
+ }
41
+
42
+ const options: any = {
43
+ method: 'POST',
44
+ headers: {
45
+ 'Content-Type': 'application/json',
46
+ },
47
+ body: JSON.stringify(data),
48
+ language: apiLanguage,
49
+ };
50
+
51
+ if (this.accessToken) {
52
+ options.headers['Authorization'] = `Bearer ${this.accessToken}`;
53
+ }
54
+
55
+ if (streaming) {
56
+ return {
57
+ async *[Symbol.asyncIterator]() {
58
+ const response = await fetch(predictionUrl, options);
59
+
60
+ if (!response.ok) {
61
+ throw new Error(`HTTP error! status: ${response.status}`);
62
+ }
63
+
64
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
65
+ // @ts-ignore
66
+ const reader = response.body.getReader();
67
+ const decoder = new TextDecoder();
68
+ let buffer = '';
69
+
70
+ try {
71
+ while (true) {
72
+ const { done, value } = await reader.read();
73
+ if (done) break;
74
+
75
+ buffer += decoder.decode(value, { stream: true });
76
+ const lines = buffer.split('\n');
77
+ buffer = lines.pop() || '';
78
+
79
+ for (const line of lines) {
80
+ if (line.trim() === '') continue;
81
+ if (line.startsWith('data:')) {
82
+ const stringifiedJson = line.replace('data:', '');
83
+ const event = JSON.parse(stringifiedJson);
84
+ yield event;
85
+ }
86
+ }
87
+ }
88
+ } finally {
89
+ reader.releaseLock();
90
+ }
91
+ },
92
+ } as unknown as Promise<PredictionResponse<T>>;
93
+ } else {
94
+ try {
95
+ const response = await fetch(predictionUrl, options);
96
+ const resp = await response.json();
97
+ return resp as Promise<PredictionResponse<T>>;
98
+ } catch (error) {
99
+ throw new Error('Error creating prediction');
100
+ }
101
+ }
102
+ }
103
+ }
package/src/models.ts ADDED
@@ -0,0 +1 @@
1
+ export type EVENT_TYPE = 'CONNECT' | 'DISCONNECT';
@@ -0,0 +1,66 @@
1
+ import { agentWidgetElementName } from './constants';
2
+ import * as ReactDom from 'react-dom';
3
+ import AgentWidget from './features/AgentWidget';
4
+ import { EVENT_TYPE } from './models';
5
+
6
+ type AgentType = {
7
+ apiHost: string;
8
+ agentId: string;
9
+ overrideConfig?: {
10
+ chatId?: string | undefined;
11
+ } & Record<string, unknown>;
12
+ theme?: {
13
+ avatar?: string;
14
+ } & Record<string, unknown>;
15
+ listeners?: Record<EVENT_TYPE, (props: any) => void>;
16
+ };
17
+
18
+ export class AgentWidgetComponent extends HTMLElement {
19
+ apiHost?: string;
20
+ agentId?: string;
21
+ overrideConfig?: {
22
+ chatId?: string | undefined;
23
+ } & Record<string, unknown>;
24
+ theme?: {
25
+ avatar?: string;
26
+ } & Record<string, unknown>;
27
+ listeners?: Record<EVENT_TYPE, (props: any) => void>;
28
+ constructor() {
29
+ super();
30
+ this.updateAttributes = this.updateAttributes.bind(this);
31
+ }
32
+
33
+ updateAttributes(attributes: AgentType) {
34
+ this.apiHost = attributes.apiHost;
35
+ this.agentId = attributes.agentId;
36
+ this.overrideConfig = attributes.overrideConfig;
37
+ this.listeners = attributes.listeners;
38
+ this.theme = attributes.theme;
39
+ this.render();
40
+ }
41
+
42
+ connectedCallback() {
43
+ if (this.apiHost) {
44
+ this.render();
45
+ }
46
+ }
47
+
48
+ render() {
49
+ ReactDom.render(
50
+ <AgentWidget
51
+ apiHost={this.apiHost || ''}
52
+ agentId={this.agentId || ''}
53
+ overrideConfig={this.overrideConfig}
54
+ listeners={this.listeners}
55
+ theme={this.theme}
56
+ />,
57
+ this
58
+ );
59
+ }
60
+ }
61
+ export const registerWebComponents = () => {
62
+ if (typeof window === 'undefined') return;
63
+ if (!customElements.get(agentWidgetElementName)) {
64
+ customElements.define(agentWidgetElementName, AgentWidgetComponent);
65
+ }
66
+ };
@@ -0,0 +1,10 @@
1
+ export const API_VERSION = '/ext/v1';
2
+ export const API_CHATS = `/chats`;
3
+
4
+ export const API_CHAT_MESSAGE = `${API_CHATS}/chatmessage`;
5
+
6
+ export const API_PREDICTION = `${API_CHATS}/prediction`;
7
+
8
+ export const API_CHATBOTS = `${API_VERSION}/bots`;
9
+
10
+ export const API_CREATE_ATTACHMENTS = `${API_CHATS}/attachments`;
@@ -0,0 +1,15 @@
1
+ import { API_CHATBOTS } from './apis';
2
+ import { BotType } from '../types/bot.type';
3
+ import { request } from '../utils/requestUtils';
4
+
5
+ export const getBot = async (id: string, apiHost: string): Promise<BotType> => {
6
+ const headers = {
7
+ 'Content-Type': 'application/json',
8
+ };
9
+
10
+ return request({
11
+ host: apiHost,
12
+ url: `${API_CHATBOTS}/${id}`,
13
+ headers,
14
+ });
15
+ };