@cmnd-ai/chatbot-react 1.7.1 → 1.9.0

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/Readme.md +239 -15
  2. package/dist/ChatProvider/index.d.ts +1 -1
  3. package/dist/ChatProvider/index.js +54 -55
  4. package/dist/ChatProvider/useChatContext.d.ts +2 -2
  5. package/dist/ChatProvider/useChatContext.js +2 -2
  6. package/dist/CmndChatBot/index.d.ts +15 -4
  7. package/dist/CmndChatBot/index.js +4 -4
  8. package/dist/components/ChatInputBox.d.ts +2 -1
  9. package/dist/components/ChatInputBox.js +3 -3
  10. package/dist/components/Chatbubble.d.ts +13 -3
  11. package/dist/components/Chatbubble.js +18 -17
  12. package/dist/components/Conversation.d.ts +8 -3
  13. package/dist/components/Conversation.js +3 -2
  14. package/dist/components/ConversationCard.d.ts +18 -0
  15. package/dist/components/ConversationCard.js +83 -0
  16. package/dist/components/ConversationsPanel/index.d.ts +46 -0
  17. package/dist/components/ConversationsPanel/index.js +355 -0
  18. package/dist/components/LoadingBubble.d.ts +14 -2
  19. package/dist/components/LoadingBubble.js +8 -7
  20. package/dist/components/ScrollToBottomButton.d.ts +10 -0
  21. package/dist/components/ScrollToBottomButton.js +57 -0
  22. package/dist/constants/endpoints.d.ts +5 -0
  23. package/dist/constants/endpoints.js +6 -0
  24. package/dist/hooks/use-fetch-data.d.ts +8 -0
  25. package/dist/hooks/use-fetch-data.js +32 -0
  26. package/dist/hooks/use-messages-scroll.d.ts +15 -0
  27. package/dist/hooks/use-messages-scroll.js +80 -0
  28. package/dist/index.d.ts +3 -1
  29. package/dist/index.js +2 -0
  30. package/dist/services/getChatBotConversationsList/index.d.ts +7 -0
  31. package/dist/services/getChatBotConversationsList/index.js +12 -0
  32. package/dist/styles/index.css +110 -0
  33. package/dist/type.d.ts +57 -0
  34. package/dist/utils/format_date/index.d.ts +2 -0
  35. package/dist/utils/format_date/index.js +32 -0
  36. package/dist/utils/getConversationLocalStorageKey/index.d.ts +5 -0
  37. package/dist/utils/getConversationLocalStorageKey/index.js +2 -0
  38. package/dist/utils/getUTCDateTime/index.d.ts +2 -0
  39. package/dist/utils/getUTCDateTime/index.js +11 -0
  40. package/dist/utils/saveConversationIdToLocalStorage/index.d.ts +6 -0
  41. package/dist/utils/saveConversationIdToLocalStorage/index.js +19 -0
  42. package/package.json +1 -1
package/Readme.md CHANGED
@@ -1,38 +1,262 @@
1
- ## @cmnd-ai/chatbot-react
1
+ # @cmnd-ai/chatbot-react
2
2
 
3
- This npm package provides a customizable chatbot component for use in web applications, designed specifically for React environments.
3
+ A fully customizable React chatbot component with conversation management, themes, and custom components support.
4
4
 
5
- ### Installation
5
+ ## Features
6
6
 
7
- You can install the `@cmnd-ai/chatbot-react` from npm using npm or yarn:
7
+ - 🤖 **Conversation Management**: Full conversation history with create, select, and delete functionality
8
+ - 🎨 **Theme Support**: Light and dark themes with customizable styling
9
+ - 🧩 **Custom Components**: Replace any UI component with your own (input fields, buttons, avatars, loading indicators)
10
+ - 💾 **Local Storage**: Automatic conversation persistence
11
+ - 📱 **Responsive Design**: Works on desktop and mobile devices
12
+ - ⚡ **Real-time Streaming**: Live message streaming with loading states
13
+ - 🛠️ **Tool Integration**: Support for UI and backend tools
14
+ - 🔄 **Auto-refresh**: Keep conversations up to date
15
+
16
+ ## Installation
8
17
 
9
18
  ```bash
10
19
  npm install @cmnd-ai/chatbot-react
11
20
  ```
12
21
 
13
- ### With yarn
22
+ or
14
23
 
15
24
  ```bash
16
25
  yarn add @cmnd-ai/chatbot-react
17
26
  ```
18
27
 
19
- ### Example implementation
28
+ ## Basic Usage
20
29
 
21
- ```javascript
22
- import { ChatProvider } from "@cmnd-ai/chatbot-react";
23
- import "@cmnd-ai/chatbot-react/dist/styles/index.css"
30
+ ```tsx
31
+ import CmndChatBot from "@cmnd-ai/chatbot-react";
32
+ import "@cmnd-ai/chatbot-react/dist/styles/index.css";
24
33
 
25
34
  const App = () => {
26
35
  return (
27
- <ChatProvider
28
- baseUrl="<your-cmnd-api-base-url>"
29
- chatbotId={"<your-chatbot-id>"}
30
- organizationId={"<your-organization-id>"}
36
+ <CmndChatBot
37
+ chatbotId={123}
38
+ organizationId={456}
39
+ apiKey="your-api-key"
40
+ baseUrl="https://api.example.com"
41
+ />
42
+ );
43
+ };
44
+ ```
45
+
46
+ ## Advanced Usage with Custom Components
47
+
48
+ ```tsx
49
+ import CmndChatBot from "@cmnd-ai/chatbot-react";
50
+ import { FaUserCircle } from "react-icons/fa";
51
+ import { BsRobot, BsTools } from "react-icons/bs";
52
+ import "@cmnd-ai/chatbot-react/dist/styles/index.css";
53
+
54
+ const App = () => {
55
+ return (
56
+ <CmndChatBot
57
+ chatbotId={123}
58
+ organizationId={456}
59
+ apiKey="your-api-key"
60
+ baseUrl="https://api.example.com"
61
+ theme="dark"
62
+ Components={{
63
+ // Custom avatar components
64
+ BotAvatar: () => <BsRobot size={24} color="#373E4E" />,
65
+ UserAvatar: () => <FaUserCircle size={24} color="#7A8194" />,
66
+ ToolAvatar: () => <BsTools size={24} color="#FF6B6B" />,
67
+
68
+ // Custom loading indicator
69
+ LoadingIndicator: () => <div>🤔 Thinking...</div>,
70
+
71
+ // Custom input field
72
+ InputField: ({ input, setInput, canSendMessage, handleSendClick }) => (
73
+ <input
74
+ type="text"
75
+ value={input}
76
+ onChange={(e) => setInput(e.target.value)}
77
+ disabled={!canSendMessage}
78
+ onKeyPress={(e) => e.key === "Enter" && handleSendClick()}
79
+ placeholder="Type your message..."
80
+ style={{
81
+ padding: "12px",
82
+ borderRadius: "8px",
83
+ border: "1px solid #ccc",
84
+ }}
85
+ />
86
+ ),
87
+
88
+ // Custom send button
89
+ SendButton: ({ canSendMessage, handleSendClick }) => (
90
+ <button
91
+ onClick={handleSendClick}
92
+ disabled={!canSendMessage}
93
+ style={{
94
+ padding: "12px 24px",
95
+ backgroundColor: canSendMessage ? "#373E4E" : "#ccc",
96
+ color: "white",
97
+ border: "none",
98
+ borderRadius: "8px",
99
+ cursor: canSendMessage ? "pointer" : "not-allowed",
100
+ }}
101
+ >
102
+ Send
103
+ </button>
104
+ ),
105
+ }}
106
+ customStyles={{
107
+ // Custom styling
108
+ panelStyle: { backgroundColor: "#f5f5f5" },
109
+ chatbubbleStyle: { borderRadius: "12px" },
110
+ botChatbubbleStyle: { backgroundColor: "#373E4E" },
111
+ userChatbubbleStyle: { backgroundColor: "#7A8194" },
112
+ }}
31
113
  />
32
114
  );
33
115
  };
116
+ ```
117
+
118
+ ## Props
119
+
120
+ ### Required Props
121
+
122
+ | Prop | Type | Description |
123
+ | ---------------- | -------- | ------------------------------- |
124
+ | `chatbotId` | `number` | Your chatbot ID |
125
+ | `organizationId` | `number` | Your organization ID |
126
+ | `baseUrl` | `string` | Your CMND API base URL |
127
+ | `apiKey` | `string` | Your API key for authentication |
128
+
129
+ ### Optional Props
130
+
131
+ | Prop | Type | Default | Description |
132
+ | --------------- | --------------------- | ----------- | --------------------------- |
133
+ | `theme` | `"light" \| "dark"` | `"light"` | Theme for the chatbot |
134
+ | `UITools` | `CMNDChatbotUITool[]` | `[]` | Array of UI tools |
135
+ | `enabledTools` | `any[]` | `[]` | Array of enabled tools |
136
+ | `initialMemory` | `CMNDChatMemory` | `undefined` | Initial conversation memory |
137
+ | `customStyles` | `CustomStyles` | `undefined` | Custom CSS styles |
138
+ | `Components` | `Components` | `undefined` | Custom component overrides |
139
+
140
+ ## Custom Components
34
141
 
35
- export default App;
142
+ You can replace any UI component with your own implementation:
143
+
144
+ ### Avatar Components
145
+
146
+ ```tsx
147
+ Components={{
148
+ BotAvatar: () => <YourBotIcon />,
149
+ UserAvatar: () => <YourUserIcon />,
150
+ ToolAvatar: () => <YourToolIcon />
151
+ }}
152
+ ```
153
+
154
+ ### Input Components
155
+
156
+ ```tsx
157
+ Components={{
158
+ InputField: ({ input, setInput, canSendMessage, handleSendClick }) => (
159
+ <YourCustomInput />
160
+ ),
161
+ SendButton: ({ canSendMessage, handleSendClick }) => (
162
+ <YourCustomButton />
163
+ )
164
+ }}
36
165
  ```
37
166
 
38
- For more information on customizing the chatbot components, please refer [here](https://github.com/CyprusCodes/cmnd-react-chatbot-example.git)
167
+ ### Loading Component
168
+
169
+ ```tsx
170
+ Components={{
171
+ LoadingIndicator: () => <YourCustomLoader />
172
+ }}
173
+ ```
174
+
175
+ ## Custom Styles
176
+
177
+ You can customize the appearance using the `customStyles` prop:
178
+
179
+ ```tsx
180
+ customStyles={{
181
+ // Panel and layout styles
182
+ panelStyle: { backgroundColor: '#f5f5f5' },
183
+ sidebarStyle: { width: '350px' },
184
+ conversationListStyle: { padding: '16px' },
185
+
186
+ // Header styles
187
+ headerStyle: { padding: '20px' },
188
+ newChatButtonStyle: { backgroundColor: '#007bff' },
189
+ refreshButtonStyle: { backgroundColor: '#28a745' },
190
+
191
+ // Conversation card styles
192
+ conversationCardStyle: { borderRadius: '8px' },
193
+ activeConversationCardStyle: { borderColor: '#007bff' },
194
+ titleStyle: { fontSize: '16px' },
195
+ dateStyle: { fontSize: '12px' },
196
+ deleteButtonStyle: { color: '#dc3545' },
197
+
198
+ // Chat bubble styles
199
+ chatbubbleStyle: { borderRadius: '12px' },
200
+ botChatbubbleStyle: { backgroundColor: '#373E4E' },
201
+ userChatbubbleStyle: { backgroundColor: '#7A8194' },
202
+ chatAvatarStyle: { fontSize: '24px' },
203
+
204
+ // Input styles
205
+ inputStyle: { padding: '12px' },
206
+ sendButtonStyle: { backgroundColor: '#373E4E' }
207
+ }}
208
+ ```
209
+
210
+ ## Conversation Management
211
+
212
+ The chatbot automatically handles:
213
+
214
+ - **Creating new conversations** when you start chatting
215
+ - **Loading existing conversations** from localStorage
216
+ - **Switching between conversations** by clicking on them
217
+ - **Deleting conversations** with the delete button
218
+ - **Auto-refreshing** conversation list
219
+ - **Persistent storage** of conversation IDs
220
+
221
+ ## Theme Support
222
+
223
+ The chatbot supports light and dark themes with automatic color schemes:
224
+
225
+ - **Light Theme**: Clean white background with dark text
226
+ - **Dark Theme**: Dark background with light text
227
+ - **Custom Colors**: Override any color with `customStyles`
228
+
229
+ ## Tool Integration
230
+
231
+ Support for both UI and backend tools:
232
+
233
+ ```tsx
234
+ const UITools = [
235
+ {
236
+ name: "calculator",
237
+ description: "Perform calculations",
238
+ category: "utility",
239
+ argumentSchema: {
240
+ type: "object",
241
+ properties: {
242
+ expression: { type: "string", description: "Math expression" },
243
+ },
244
+ },
245
+ runCmd: ({ functionArgs }) => {
246
+ // Your tool implementation
247
+ },
248
+ },
249
+ ];
250
+ ```
251
+
252
+ ## Examples
253
+
254
+ For more detailed examples and implementations, check out our [example repository](https://github.com/CyprusCodes/cmnd-react-chatbot-example.git).
255
+
256
+ ## Contributing
257
+
258
+ We welcome contributions! Please feel free to submit a Pull Request.
259
+
260
+ ## License
261
+
262
+ This project is licensed under the MIT License.
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { CmndChatBotProps } from "../CmndChatBot/index.js";
3
3
  import { CmndChatContext, CMNDChatMemory } from "../type.js";
4
4
  export declare const ChatProviderContext: React.Context<CmndChatContext | undefined>;
5
- export interface ChatProviderProps extends CmndChatBotProps {
5
+ export interface ChatProviderProps extends Omit<CmndChatBotProps, "postSessionMessage"> {
6
6
  children?: React.ReactNode | ((props: CmndChatBotProps) => React.ReactNode);
7
7
  }
8
8
  export declare const setCurrentConversationMemory: (memory: CMNDChatMemory) => Promise<import("axios").AxiosResponse<any, any> | undefined>;
@@ -1,13 +1,12 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useEffect, useRef, useState } from "react";
3
- import { MessageRole, } from "../type.js";
4
3
  import postUserConversation from "../services/postUserConversation.js";
5
- import Conversation from "../components/Conversation.js";
6
4
  import getChatBotById from "../services/getchatBotById.js";
7
5
  import patchChatbotConversationMemory from "../services/patchChatbotConversationMemory/index.js";
8
6
  import deleteChatbotConversationMemory from "../services/deleteChatbotConversationMemory/index.js";
9
7
  import parseUITools from "../utils/parseUITools.js";
10
8
  import getTools from "../utils/getTools/index.js";
9
+ import { ConversationsPanel, } from "../components/ConversationsPanel/index.js";
11
10
  let globalChatbotConversationId;
12
11
  let globalChatbotProps;
13
12
  export const ChatProviderContext = React.createContext(undefined);
@@ -55,9 +54,14 @@ function ChatProvider(props) {
55
54
  const [canContinue] = useState(false);
56
55
  const [isChatLoading, setIsChatLoading] = useState(false);
57
56
  const [canSendMessage, setCanSendMessage] = useState(true);
58
- const messagesRef = useRef(null);
59
57
  const [chatbotConversationId, setChatbotConversationId] = useState(undefined);
60
58
  const [enabledTools, setEnabledTools] = useState([]);
59
+ const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
60
+ const [selectedConversation, setSelectedConversation] = useState(null);
61
+ const inputRef = useRef(null);
62
+ const [shouldFocusInput, setShouldFocusInput] = useState(false);
63
+ const [pendingSendText, setPendingSendText] = useState(null);
64
+ const conversationsPanelRef = useRef(null);
61
65
  useEffect(() => {
62
66
  globalChatbotConversationId = chatbotConversationId;
63
67
  }, [chatbotConversationId]);
@@ -75,14 +79,6 @@ function ChatProvider(props) {
75
79
  setLoading(false);
76
80
  });
77
81
  }, [organizationId, chatbotId]);
78
- useEffect(() => {
79
- scrollToBottom();
80
- }, [messages, canSendMessage]);
81
- const scrollToBottom = () => {
82
- if (messagesRef.current) {
83
- messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
84
- }
85
- };
86
82
  const postSessionMessage = async (newMessages, onData) => {
87
83
  if (!organizationId || !chatbotId)
88
84
  return;
@@ -104,50 +100,48 @@ function ChatProvider(props) {
104
100
  onData,
105
101
  });
106
102
  };
107
- const handleSendClick = async () => {
108
- if (input.trim() === "" || !canSendMessage)
109
- return;
110
- const newUserMessage = {
111
- unuseful: false,
112
- hiddenFromUser: false,
113
- role: "user",
114
- message: canContinue ? "continue" : input,
115
- };
116
- const newMessages = [...messages, newUserMessage];
117
- setMessages(newMessages);
118
- setInput("");
119
- setIsChatLoading(true);
120
- try {
121
- const onData = (data) => {
122
- if (data.finalResponseWithUsageData) {
123
- setIsChatLoading(false);
124
- setCanSendMessage(true);
125
- const { chatbotConversationId, messages } = data;
126
- if (chatbotConversationId) {
127
- setChatbotConversationId(chatbotConversationId);
128
- }
129
- messages && setMessages(messages);
130
- }
131
- if (data.message) {
132
- setIsChatLoading(false);
133
- const newAssistantMessage = {
134
- unuseful: false,
135
- hiddenFromUser: false,
136
- role: MessageRole.ASSISTANT,
137
- message: data.message,
138
- };
139
- setMessages([...newMessages, newAssistantMessage]);
140
- scrollToBottom();
141
- }
142
- };
143
- setCanSendMessage(false);
144
- await postSessionMessage(newMessages, onData);
103
+ const toggleSidebar = () => {
104
+ setIsSidebarCollapsed((prev) => !prev);
105
+ };
106
+ const openSidePanel = () => {
107
+ setIsSidebarCollapsed(false);
108
+ };
109
+ const closeSidePanel = () => {
110
+ setIsSidebarCollapsed(true);
111
+ };
112
+ const createNewConversation = () => {
113
+ conversationsPanelRef.current?.handleNewChat();
114
+ };
115
+ const setMessageText = (text) => {
116
+ setInput(text);
117
+ setShouldFocusInput(true);
118
+ };
119
+ useEffect(() => {
120
+ if (shouldFocusInput) {
121
+ inputRef.current?.focus();
122
+ if (inputRef.current) {
123
+ const len = inputRef.current.value.length;
124
+ inputRef.current.setSelectionRange(len, len);
125
+ }
126
+ setShouldFocusInput(false);
145
127
  }
146
- catch (error) {
147
- console.error(error);
148
- setError("Error sending message");
128
+ }, [input, shouldFocusInput]);
129
+ const sendMessage = (text) => {
130
+ if (typeof text === "string") {
131
+ setInput(text);
132
+ setShouldFocusInput(true);
133
+ setPendingSendText(text);
134
+ }
135
+ else {
136
+ conversationsPanelRef.current?.handleSendClick();
149
137
  }
150
138
  };
139
+ useEffect(() => {
140
+ if (pendingSendText !== null && input === pendingSendText) {
141
+ conversationsPanelRef.current?.handleSendClick();
142
+ setPendingSendText(null);
143
+ }
144
+ }, [input, pendingSendText]);
151
145
  if (loading)
152
146
  return null;
153
147
  return (_jsx(ChatProviderContext.Provider, { value: {
@@ -164,7 +158,6 @@ function ChatProvider(props) {
164
158
  setChatbotConversationId,
165
159
  setIsChatLoading,
166
160
  setCanSendMessage,
167
- scrollToBottom,
168
161
  enabledTools: getTools({
169
162
  apiTools: enabledTools,
170
163
  uiTools: parseUITools(UITools),
@@ -172,9 +165,15 @@ function ChatProvider(props) {
172
165
  chatbotConversationId,
173
166
  UITools: parseUITools(UITools),
174
167
  },
175
- }, children: error ? (_jsx("div", { children: "An error occured" })) : (_jsxs(_Fragment, { children: [props.children, _jsx(Conversation, { messages: messages, setMessages: setMessages, postSessionMessage: postSessionMessage, isChatLoading: isChatLoading, messagesRef: messagesRef, input: input, setInput: setInput, handleSendClick: handleSendClick, setChatbotConversationId: setChatbotConversationId, setIsChatLoading: setIsChatLoading, setCanSendMessage: setCanSendMessage, canSendMessage: canSendMessage, scrollToBottom: scrollToBottom, error: error, enabledTools: getTools({
168
+ createNewConversation,
169
+ toggleSidebar,
170
+ openSidePanel,
171
+ closeSidePanel,
172
+ setMessageText,
173
+ sendMessage,
174
+ }, children: error ? (_jsx("div", { children: "An error occured" })) : (_jsxs(_Fragment, { children: [props.children, _jsx(ConversationsPanel, { ref: conversationsPanelRef, organizationId: organizationId, chatbotId: chatbotId, baseUrl: baseUrl, theme: props.theme, enabledTools: getTools({
176
175
  apiTools: enabledTools,
177
176
  uiTools: parseUITools(UITools),
178
- }), Components: Components, UITools: parseUITools(UITools), customStyles: props.customStyles, chatbotConversationId: chatbotConversationId, setCurrentConversationMemory: setCurrentConversationMemory })] })) }));
177
+ }), postSessionMessage: postSessionMessage, setChatbotConversationId: setChatbotConversationId, chatbotConversationId: chatbotConversationId, Components: Components, UITools: parseUITools(UITools), customStyles: props.customStyles, isSidebarCollapsed: isSidebarCollapsed, setIsSidebarCollapsed: setIsSidebarCollapsed, selectedConversation: selectedConversation, setSelectedConversation: setSelectedConversation, messages: messages, setMessages: setMessages, input: input, setInput: setInput, inputRef: inputRef })] })) }));
179
178
  }
180
179
  export default ChatProvider;
@@ -1,2 +1,2 @@
1
- declare const useChatContext: () => import("../type.js").CmndChatContext;
2
- export default useChatContext;
1
+ declare const useCMNDChatContext: () => import("../type.js").CmndChatContext;
2
+ export { useCMNDChatContext };
@@ -1,9 +1,9 @@
1
1
  import { useContext } from "react";
2
2
  import { ChatProviderContext } from "./index.js";
3
- const useChatContext = () => {
3
+ const useCMNDChatContext = () => {
4
4
  const context = useContext(ChatProviderContext);
5
5
  if (!context)
6
6
  throw new Error("Cmnd chat context must be wrapped in a provider");
7
7
  return context;
8
8
  };
9
- export default useChatContext;
9
+ export { useCMNDChatContext };
@@ -1,13 +1,24 @@
1
- import { CMNDChatbotUITool, CMNDChatMemory, CustomStyles } from "../type.js";
2
- import { ConversationProps } from "../components/Conversation.js";
3
- export interface CmndChatBotProps extends Pick<ConversationProps, "Components"> {
1
+ /// <reference types="react" />
2
+ import { CMNDChatbotUITool, CMNDChatMemory, CustomStyles, InputFieldProps, SendButtonProps } from "../type.js";
3
+ export interface CmndChatBotProps {
4
4
  chatbotId: number;
5
5
  organizationId: number;
6
6
  apiKey?: string;
7
7
  baseUrl: string;
8
+ theme?: "light" | "dark";
8
9
  UITools?: CMNDChatbotUITool[];
9
10
  customStyles?: CustomStyles;
10
11
  initialMemory?: CMNDChatMemory;
12
+ enabledTools?: any[];
13
+ Components?: {
14
+ InputField?: (params: InputFieldProps) => JSX.Element;
15
+ SendButton?: (params: SendButtonProps) => JSX.Element;
16
+ BotAvatar?: () => JSX.Element;
17
+ UserAvatar?: () => JSX.Element;
18
+ ToolAvatar?: () => JSX.Element;
19
+ LoadingIndicator?: () => JSX.Element;
20
+ error?: any;
21
+ };
11
22
  }
12
- declare function CmndChatBot(): import("../type.js").CmndChatContext;
23
+ declare function CmndChatBot({ chatbotId, organizationId, apiKey, baseUrl, theme, UITools, customStyles, enabledTools, Components, initialMemory, }: CmndChatBotProps): JSX.Element;
13
24
  export default CmndChatBot;
@@ -1,6 +1,6 @@
1
- import useChatContext from "../ChatProvider/useChatContext.js";
2
- function CmndChatBot() {
3
- const chatContext = useChatContext();
4
- return chatContext;
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import ChatProvider from "../ChatProvider/index.js";
3
+ function CmndChatBot({ chatbotId, organizationId, apiKey, baseUrl, theme, UITools, customStyles, enabledTools = [], Components, initialMemory, }) {
4
+ return (_jsx(ChatProvider, { chatbotId: chatbotId, organizationId: organizationId, apiKey: apiKey, baseUrl: baseUrl, theme: theme, UITools: UITools, customStyles: customStyles, enabledTools: enabledTools, Components: Components, initialMemory: initialMemory }));
5
5
  }
6
6
  export default CmndChatBot;
@@ -3,6 +3,7 @@ interface ChatInputBoxProps {
3
3
  input: string;
4
4
  setInput: (input: string) => void;
5
5
  handleSendClick: () => void;
6
+ inputRef?: React.RefObject<HTMLInputElement>;
6
7
  }
7
- declare const ChatInputBox: ({ input, setInput, handleSendClick }: ChatInputBoxProps) => JSX.Element;
8
+ declare const ChatInputBox: ({ input, setInput, handleSendClick, inputRef, }: ChatInputBoxProps) => JSX.Element;
8
9
  export default ChatInputBox;
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- const ChatInputBox = ({ input, setInput, handleSendClick }) => {
3
- return (_jsx("div", { className: "cmnd-input-wrapper", children: _jsx("input", { autoFocus: true, id: "cmnd-input", className: "cmnd-input", onKeyDown: e => {
2
+ const ChatInputBox = ({ input, setInput, handleSendClick, inputRef, }) => {
3
+ return (_jsx("div", { className: "cmnd-input-wrapper", children: _jsx("input", { ref: inputRef, autoFocus: true, id: "cmnd-input", className: "cmnd-input", onKeyDown: (e) => {
4
4
  if (e.key === "Enter") {
5
5
  handleSendClick();
6
6
  }
7
- }, autoComplete: "off", value: input, onChange: e => setInput(e.target.value), type: "text", placeholder: "Type something..." }) }));
7
+ }, autoComplete: "off", value: input, onChange: (e) => setInput(e.target.value), type: "text", placeholder: "Type something..." }) }));
8
8
  };
9
9
  export default ChatInputBox;
@@ -1,5 +1,5 @@
1
1
  import { Dispatch, ReactNode, SetStateAction } from "react";
2
- import { MessageRole, ToolDetails, ToolData, CustomStyles, CMNDChatbotUITool } from "../type.js";
2
+ import { MessageRole, ToolDetails, ToolData, CustomStyles, CMNDChatbotUITool, InputFieldProps, SendButtonProps } from "../type.js";
3
3
  interface ChatBubbleProps {
4
4
  message: string | ReactNode | null;
5
5
  role: MessageRole;
@@ -14,9 +14,19 @@ interface ChatBubbleProps {
14
14
  setChatbotConversationId: Dispatch<SetStateAction<number | undefined>>;
15
15
  setCanSendMessage: Dispatch<SetStateAction<boolean>>;
16
16
  setIsChatLoading: Dispatch<SetStateAction<boolean>>;
17
- scrollToBottom: () => void;
18
17
  UITools?: CMNDChatbotUITool[];
19
18
  customStyles?: CustomStyles;
19
+ chatbotId: number;
20
+ organizationId: number;
21
+ theme?: "light" | "dark";
22
+ Components?: {
23
+ InputField?: (params: InputFieldProps) => JSX.Element;
24
+ SendButton?: (params: SendButtonProps) => JSX.Element;
25
+ BotAvatar?: () => JSX.Element;
26
+ UserAvatar?: () => JSX.Element;
27
+ ToolAvatar?: () => JSX.Element;
28
+ error?: any;
29
+ };
20
30
  }
21
- declare const Chatbubble: ({ message, role, toolCallDetails, tools, postSessionMessage, setMessages, messages, hide, setChatbotConversationId, setCanSendMessage, setIsChatLoading, scrollToBottom, isLoadingBubble, UITools, customStyles, }: ChatBubbleProps) => JSX.Element | null;
31
+ declare const Chatbubble: ({ message, role, toolCallDetails, tools, postSessionMessage, setMessages, messages, hide, setChatbotConversationId, setCanSendMessage, setIsChatLoading, isLoadingBubble, UITools, customStyles, chatbotId, organizationId, theme, Components, }: ChatBubbleProps) => JSX.Element | null;
22
32
  export default Chatbubble;
@@ -11,6 +11,7 @@ import SyntaxHighlighter from "react-syntax-highlighter";
11
11
  //@ts-ignore
12
12
  import oneDark from "react-syntax-highlighter/dist/cjs/styles/prism/one-dark.js";
13
13
  import { overrideStyle } from "../utils.js";
14
+ import saveConversationIdToLocalStorage from "../utils/saveConversationIdToLocalStorage/index.js";
14
15
  const patchLastMessageToolInfo = (messages, toolInfo) => {
15
16
  console.log("patchLastMessageToolInfo", messages, toolInfo);
16
17
  const lastMessage = messages[messages.length - 1];
@@ -26,25 +27,25 @@ const patchLastMessageToolInfo = (messages, toolInfo) => {
26
27
  const newMessages = [...shallowCopyOfMessagesWithoutLast, copyOfLastMessage];
27
28
  return newMessages;
28
29
  };
29
- const confirmToolRun = async ({ messages, setMessages, postSessionMessage, setIsChatLoading, setCanSendMessage, setChatbotConversationId, scrollToBottom, }) => {
30
+ const confirmToolRun = async ({ messages, setMessages, postSessionMessage, setIsChatLoading, setCanSendMessage, setChatbotConversationId, chatbotId, organizationId, }) => {
30
31
  const newMessages = patchLastMessageToolInfo(messages, {
31
32
  confirmed: true,
32
33
  });
33
34
  setIsChatLoading(true);
34
35
  setCanSendMessage(false);
35
36
  setMessages(newMessages);
36
- await postSessionMessage(newMessages, (data) => {
37
+ await postSessionMessage(newMessages, async (data) => {
37
38
  if (data.finalResponseWithUsageData) {
38
39
  setCanSendMessage(true);
39
40
  setIsChatLoading(false);
40
41
  const { messages, chatbotConversationId } = data;
41
42
  if (chatbotConversationId) {
42
43
  setChatbotConversationId(chatbotConversationId);
43
- // saveConversationIdToLocalStorage(
44
- // chatbotConversationId.toString(),
45
- // config.chatbot_id!,
46
- // config.organization_id!
47
- // );
44
+ await saveConversationIdToLocalStorage({
45
+ chatbotConversationId,
46
+ chatbotId,
47
+ organizationId,
48
+ });
48
49
  }
49
50
  messages && setMessages(messages);
50
51
  }
@@ -58,23 +59,23 @@ const confirmToolRun = async ({ messages, setMessages, postSessionMessage, setIs
58
59
  };
59
60
  newAssistantMessage.message = data.message;
60
61
  setMessages([...newMessages, newAssistantMessage]);
61
- scrollToBottom();
62
62
  }
63
63
  });
64
64
  };
65
- const getChatAvatar = (role) => {
65
+ const getChatAvatar = (role, theme = "light", Components) => {
66
+ const iconColor = theme === "dark" ? "#ffffff" : "#000000";
66
67
  switch (role) {
67
68
  case MessageRole.USER:
68
- return _jsx(FaUserCircle, {});
69
+ return Components?.UserAvatar ? (_jsx(Components.UserAvatar, {})) : (_jsx(FaUserCircle, { color: iconColor }));
69
70
  case MessageRole.FUNCTION:
70
- return _jsx(BsTools, {});
71
+ return Components?.ToolAvatar ? (_jsx(Components.ToolAvatar, {})) : (_jsx(BsTools, { color: iconColor }));
71
72
  case MessageRole.ASSISTANT:
72
- return _jsx(BsRobot, {});
73
+ return Components?.BotAvatar ? (_jsx(Components.BotAvatar, {})) : (_jsx(BsRobot, { color: iconColor }));
73
74
  default:
74
- return _jsx(BsRobot, {});
75
+ return _jsx(BsRobot, { color: iconColor });
75
76
  }
76
77
  };
77
- const Chatbubble = ({ message, role, toolCallDetails, tools, postSessionMessage, setMessages, messages, hide, setChatbotConversationId, setCanSendMessage, setIsChatLoading, scrollToBottom, isLoadingBubble, UITools, customStyles, }) => {
78
+ const Chatbubble = ({ message, role, toolCallDetails, tools, postSessionMessage, setMessages, messages, hide, setChatbotConversationId, setCanSendMessage, setIsChatLoading, isLoadingBubble, UITools, customStyles, chatbotId, organizationId, theme, Components, }) => {
78
79
  const toolData = tools?.find((t) => t.name === toolCallDetails?.name);
79
80
  const hasConfirmedToolRun = useRef(false);
80
81
  const isPostingMessage = useRef(false);
@@ -92,7 +93,8 @@ const Chatbubble = ({ message, role, toolCallDetails, tools, postSessionMessage,
92
93
  setIsChatLoading,
93
94
  setCanSendMessage,
94
95
  setChatbotConversationId,
95
- scrollToBottom,
96
+ chatbotId,
97
+ organizationId,
96
98
  });
97
99
  }
98
100
  }, []);
@@ -120,7 +122,7 @@ const Chatbubble = ({ message, role, toolCallDetails, tools, postSessionMessage,
120
122
  return (_jsxs("div", { style: defaultStyle, className: `cmnd-chatbot-chat-bubble ${role}`, children: [_jsx("span", { style: overrideStyle({
121
123
  fontSize: "30px",
122
124
  color: "black",
123
- }, customStyles?.chatAvatarStyle), children: getChatAvatar(role) }), _jsxs("span", { style: chatBubbleCustomStyle, children: [role === MessageRole.USER || isLoadingBubble ? (_jsx("span", { children: message })) : (_jsx(ReactMarkdown, { className: "markdown", remarkPlugins: [remarkGfm], children: message?.toString() ?? "", remarkRehypeOptions: { passThrough: ["link"] }, components: {
125
+ }, customStyles?.chatAvatarStyle), children: getChatAvatar(role, theme, Components) }), _jsxs("span", { style: chatBubbleCustomStyle, children: [role === MessageRole.USER || isLoadingBubble ? (_jsx("span", { children: message })) : (_jsx(ReactMarkdown, { className: "markdown", remarkPlugins: [remarkGfm], children: message?.toString() ?? "", remarkRehypeOptions: { passThrough: ["link"] }, components: {
124
126
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
125
127
  // @ts-ignore
126
128
  code({ inline, className, children, ...props }) {
@@ -165,7 +167,6 @@ const Chatbubble = ({ message, role, toolCallDetails, tools, postSessionMessage,
165
167
  message: data.message,
166
168
  };
167
169
  setMessages([...newMessages, newAssistantMessage]);
168
- scrollToBottom();
169
170
  }
170
171
  };
171
172
  try {