@cmnd-ai/chatbot-react 1.9.2 → 1.13.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 (34) hide show
  1. package/Readme.md +113 -9
  2. package/dist/ChatProvider/index.d.ts +2 -2
  3. package/dist/ChatProvider/index.js +13 -13
  4. package/dist/ChatProvider/processStream/index.js +40 -15
  5. package/dist/CmndChatBot/index.d.ts +2 -1
  6. package/dist/CmndChatBot/index.js +2 -2
  7. package/dist/components/Chatbubble.d.ts +2 -2
  8. package/dist/components/Chatbubble.js +11 -11
  9. package/dist/components/Conversation.d.ts +3 -3
  10. package/dist/components/Conversation.js +2 -2
  11. package/dist/components/ConversationCard.js +1 -1
  12. package/dist/components/ConversationsPanel/index.d.ts +2 -2
  13. package/dist/components/ConversationsPanel/index.js +25 -23
  14. package/dist/components/LoadingBubble.js +1 -1
  15. package/dist/constants/endpoints.d.ts +3 -3
  16. package/dist/constants/endpoints.js +2 -2
  17. package/dist/hooks/use-cmnd-chat.d.ts +130 -0
  18. package/dist/hooks/use-cmnd-chat.js +396 -0
  19. package/dist/index.d.ts +4 -1
  20. package/dist/index.js +4 -0
  21. package/dist/services/deleteChatbotConversationMemory/index.d.ts +2 -2
  22. package/dist/services/deleteChatbotConversationMemory/index.js +2 -2
  23. package/dist/services/getChatBotConversationsList/index.d.ts +1 -1
  24. package/dist/services/getEmbedChatBotById.d.ts +1 -1
  25. package/dist/services/patchChatbotConversationMemory/index.d.ts +2 -2
  26. package/dist/services/patchChatbotConversationMemory/index.js +2 -2
  27. package/dist/type.d.ts +134 -41
  28. package/dist/type.js +12 -0
  29. package/dist/utils/cleanMarkdown.d.ts +8 -0
  30. package/dist/utils/cleanMarkdown.js +31 -0
  31. package/dist/utils/saveConversationIdToLocalStorage/index.d.ts +2 -2
  32. package/dist/utils/saveConversationIdToLocalStorage/index.js +8 -7
  33. package/package.json +4 -3
  34. package/readme.dev.md +49 -0
@@ -10,11 +10,11 @@ import getConversationLocalStorageKey from "../../utils/getConversationLocalStor
10
10
  import saveConversationIdToLocalStorage from "../../utils/saveConversationIdToLocalStorage/index.js";
11
11
  import getUTCDateTime from "../../utils/getUTCDateTime/index.js";
12
12
  import useMessagesScroll from "../../hooks/use-messages-scroll.js";
13
- export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseUrl, chatHistoryStorageKey, theme = "light", enabledTools = [], setChatbotConversationId, chatbotConversationId, postSessionMessage, Components, UITools, customStyles, isSidebarCollapsed, setIsSidebarCollapsed, selectedConversation, setSelectedConversation, messages, setMessages, input, setInput, inputRef, }, ref) => {
13
+ import { v4 as uuidv4 } from "uuid";
14
+ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseUrl, chatHistoryStorageKey, theme = "light", enabledTools = [], setChatbotConversationRef, chatbotConversationRef, postSessionMessage, Components, UITools, customStyles, isSidebarCollapsed, setIsSidebarCollapsed, selectedConversation, setSelectedConversation, messages, setMessages, input, setInput, inputRef, }, ref) => {
14
15
  const [isChatLoading, setIsChatLoading] = useState(false);
15
16
  const [canSendMessage, setCanSendMessage] = useState(true);
16
17
  const [conversationIds, setConversationIds] = useState([]);
17
- const isSidebarCollapsedProp = typeof isSidebarCollapsed === "boolean" ? isSidebarCollapsed : false;
18
18
  const setIsSidebarCollapsedProp = setIsSidebarCollapsed;
19
19
  const [internalSidebarCollapsed, setInternalSidebarCollapsed] = useState(false);
20
20
  const isSidebarCollapsedFinal = typeof isSidebarCollapsed === "boolean"
@@ -51,10 +51,11 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
51
51
  },
52
52
  };
53
53
  const colors = themeColors[theme];
54
- const localStorageKey = chatHistoryStorageKey || getConversationLocalStorageKey({
55
- organizationId,
56
- chatbotId,
57
- });
54
+ const localStorageKey = chatHistoryStorageKey ||
55
+ getConversationLocalStorageKey({
56
+ organizationId,
57
+ chatbotId,
58
+ });
58
59
  useEffect(() => {
59
60
  try {
60
61
  const conversationsFromLocalStorage = JSON.parse(localStorage.getItem(localStorageKey) || "[]") ?? [];
@@ -75,7 +76,7 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
75
76
  setConversationIds([]);
76
77
  }
77
78
  };
78
- const { data, loading, error, refetch } = useFetchData(async () => {
79
+ const { data, loading, error } = useFetchData(async () => {
79
80
  // Only fetch if we have conversation IDs
80
81
  if (conversationIds.length === 0) {
81
82
  return { chatbotConversations: [] };
@@ -116,11 +117,11 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
116
117
  if (data.finalResponseWithUsageData) {
117
118
  setIsChatLoading(false);
118
119
  setCanSendMessage(true);
119
- const { chatbotConversationId: newConversationId, messages: updatedMessages, } = data;
120
+ const { chatbotConversationRef: newConversationId, messages: updatedMessages, } = data;
120
121
  if (newConversationId) {
121
- setChatbotConversationId(newConversationId);
122
+ setChatbotConversationRef(newConversationId);
122
123
  await saveConversationIdToLocalStorage({
123
- chatbotConversationId: newConversationId,
124
+ chatbotConversationRef: newConversationId,
124
125
  chatbotId,
125
126
  organizationId,
126
127
  chatHistoryStorageKey,
@@ -131,7 +132,7 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
131
132
  "New Conversation") {
132
133
  setSelectedConversation({
133
134
  ...selectedConversation,
134
- chatbotConversationId: newConversationId,
135
+ chatbotConversationRef: newConversationId,
135
136
  chatbotConversationTitle: input.substring(0, 50) + (input.length > 50 ? "..." : ""),
136
137
  messages: updatedMessages || newMessages,
137
138
  });
@@ -162,7 +163,7 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
162
163
  };
163
164
  const handleConversationSelect = (conversation) => {
164
165
  setSelectedConversation(conversation);
165
- setChatbotConversationId(conversation.chatbotConversationId);
166
+ setChatbotConversationRef(conversation.chatbotConversationRef);
166
167
  const formattedMessages = conversation.messages.map((msg) => ({
167
168
  ...msg,
168
169
  id: msg.id || Date.now().toString(),
@@ -171,12 +172,12 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
171
172
  };
172
173
  const handleNewChat = () => {
173
174
  setSelectedConversation(null);
174
- setChatbotConversationId(undefined);
175
+ setChatbotConversationRef(undefined);
175
176
  setMessages([]);
176
177
  setInput("");
177
178
  const dateString = getUTCDateTime();
178
179
  const newConversation = {
179
- chatbotConversationId: Date.now(),
180
+ chatbotConversationRef: uuidv4(),
180
181
  messages: [],
181
182
  chatbotId: chatbotId,
182
183
  chatbotConversationTitle: "New Conversation",
@@ -192,10 +193,10 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
192
193
  const currentConversations = JSON.parse(localStorage.getItem(localStorageKey) || "[]") ?? [];
193
194
  const updatedConversations = currentConversations.filter((id) => id !== conversationId);
194
195
  localStorage.setItem(localStorageKey, JSON.stringify(updatedConversations));
195
- if (selectedConversation?.chatbotConversationId === conversationId) {
196
+ if (selectedConversation?.chatbotConversationRef === conversationId) {
196
197
  setSelectedConversation(null);
197
198
  setMessages([]);
198
- setChatbotConversationId(undefined);
199
+ setChatbotConversationRef(undefined);
199
200
  }
200
201
  refetchConversationIds();
201
202
  }
@@ -207,6 +208,7 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
207
208
  console.log("Set conversation memory:", memory);
208
209
  };
209
210
  const allConversations = React.useMemo(() => {
211
+ console.log("data", data?.chatbotConversations);
210
212
  const existingConversations = data?.chatbotConversations || [];
211
213
  const newConversation = selectedConversation &&
212
214
  selectedConversation.chatbotConversationTitle === "New Conversation"
@@ -217,8 +219,8 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
217
219
  conversations.push(newConversation);
218
220
  }
219
221
  return conversations.sort((a, b) => {
220
- const dateA = new Date(a.updatedAt);
221
- const dateB = new Date(b.updatedAt);
222
+ const dateA = new Date(a.updatedAt ?? a.createdAt);
223
+ const dateB = new Date(b.updatedAt ?? b.createdAt);
222
224
  return dateB.getTime() - dateA.getTime();
223
225
  });
224
226
  }, [data?.chatbotConversations, selectedConversation]);
@@ -316,8 +318,8 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
316
318
  textAlign: "center",
317
319
  padding: "20px",
318
320
  color: colors.secondaryText,
319
- }, children: "No conversations yet" })) : (allConversations.map((conversation) => (_jsx(ConversationCard, { conversation: conversation, isActive: selectedConversation?.chatbotConversationId ===
320
- conversation.chatbotConversationId, onClick: () => {
321
+ }, children: "No conversations yet" })) : (allConversations.map((conversation) => (_jsx(ConversationCard, { conversation: conversation, isActive: selectedConversation?.chatbotConversationRef ===
322
+ conversation.chatbotConversationRef, onClick: () => {
321
323
  if (conversation.chatbotConversationTitle ===
322
324
  "New Conversation") {
323
325
  }
@@ -331,7 +333,7 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
331
333
  setMessages([]);
332
334
  }
333
335
  else {
334
- handleDeleteConversation(conversation.chatbotConversationId);
336
+ handleDeleteConversation(conversation.chatbotConversationRef);
335
337
  }
336
338
  }, theme: theme, customStyles: {
337
339
  conversationCardStyle: customStyles?.conversationCardStyle,
@@ -339,7 +341,7 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
339
341
  titleStyle: customStyles?.titleStyle,
340
342
  dateStyle: customStyles?.dateStyle,
341
343
  deleteButtonStyle: customStyles?.deleteButtonStyle,
342
- } }, conversation.chatbotConversationId)))) })] }), _jsx("div", { className: "cmnd-chat-area", style: {
344
+ } }, conversation.chatbotConversationRef)))) })] }), _jsx("div", { className: "cmnd-chat-area", style: {
343
345
  flex: 1,
344
346
  display: "flex",
345
347
  flexDirection: "column",
@@ -352,5 +354,5 @@ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseU
352
354
  fontSize: "16px",
353
355
  textAlign: "center",
354
356
  padding: "20px",
355
- }, children: _jsx("div", { children: _jsx("div", { children: "Select a conversation or start a new one" }) }) })) : (_jsx(Conversation, { messages: messages, setMessages: setMessages, handleSendClick: handleSendClick, input: input, setInput: setInput, isChatLoading: isChatLoading, error: error ? "Error loading conversations" : null, messagesRef: messagesRef, setChatbotConversationId: setChatbotConversationId, chatbotConversationId: chatbotConversationId, setIsChatLoading: setIsChatLoading, setCanSendMessage: setCanSendMessage, canSendMessage: canSendMessage, enabledTools: enabledTools, postSessionMessage: postSessionMessage, theme: theme, Components: Components, UITools: UITools, customStyles: customStyles, setCurrentConversationMemory: setCurrentConversationMemory, chatbotId: chatbotId, organizationId: organizationId, chatHistoryStorageKey: chatHistoryStorageKey, isMessagesScrolledToBottom: isMessagesScrolledToBottom, resetMessagesScroll: resetMessagesScroll, inputRef: inputRef })) })] }));
357
+ }, children: _jsx("div", { children: _jsx("div", { children: "Select a conversation or start a new one" }) }) })) : (_jsx(Conversation, { messages: messages, setMessages: setMessages, handleSendClick: handleSendClick, input: input, setInput: setInput, isChatLoading: isChatLoading, error: error ? "Error loading conversations" : null, messagesRef: messagesRef, setChatbotConversationRef: setChatbotConversationRef, chatbotConversationRef: chatbotConversationRef, setIsChatLoading: setIsChatLoading, setCanSendMessage: setCanSendMessage, canSendMessage: canSendMessage, enabledTools: enabledTools, postSessionMessage: postSessionMessage, theme: theme, Components: Components, UITools: UITools, customStyles: customStyles, setCurrentConversationMemory: setCurrentConversationMemory, chatbotId: chatbotId, organizationId: organizationId, chatHistoryStorageKey: chatHistoryStorageKey, isMessagesScrolledToBottom: isMessagesScrolledToBottom, resetMessagesScroll: resetMessagesScroll, inputRef: inputRef })) })] }));
356
358
  });
@@ -8,6 +8,6 @@ const LoadingBubble = ({ customStyles, chatbotId, organizationId, theme, Compone
8
8
  display: "block",
9
9
  shapeRendering: "auto",
10
10
  }, width: "60px", height: "30px", viewBox: "0 0 100 100", preserveAspectRatio: "xMidYMid", children: [_jsxs("circle", { cx: "84", cy: "50", r: "10", fill: "#000", children: [_jsx("animate", { attributeName: "r", repeatCount: "indefinite", dur: "0.25s", calcMode: "spline", keyTimes: "0;1", values: "10;0", keySplines: "0 0.5 0.5 1", begin: "0s" }), _jsx("animate", { attributeName: "fill", repeatCount: "indefinite", dur: "1s", calcMode: "discrete", keyTimes: "0;0.25;0.5;0.75;1", values: color, begin: "0s" })] }), _jsxs("circle", { cx: "16", cy: "50", r: "10", fill: color, children: [_jsx("animate", { attributeName: "r", repeatCount: "indefinite", dur: "1s", calcMode: "spline", keyTimes: "0;0.25;0.5;0.75;1", values: "0;0;10;10;10", keySplines: "0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1", begin: "0s" }), _jsx("animate", { attributeName: "cx", repeatCount: "indefinite", dur: "1s", calcMode: "spline", keyTimes: "0;0.25;0.5;0.75;1", values: "16;16;16;50;84", keySplines: "0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1", begin: "0s" })] }), _jsxs("circle", { cx: "50", cy: "50", r: "10", fill: color, children: [_jsx("animate", { attributeName: "r", repeatCount: "indefinite", dur: "1s", calcMode: "spline", keyTimes: "0;0.25;0.5;0.75;1", values: "0;0;10;10;10", keySplines: "0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1", begin: "-0.25s" }), _jsx("animate", { attributeName: "cx", repeatCount: "indefinite", dur: "1s", calcMode: "spline", keyTimes: "0;0.25;0.5;0.75;1", values: "16;16;16;50;84", keySplines: "0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1", begin: "-0.25s" })] }), _jsxs("circle", { cx: "84", cy: "50", r: "10", fill: color, children: [_jsx("animate", { attributeName: "r", repeatCount: "indefinite", dur: "1s", calcMode: "spline", keyTimes: "0;0.25;0.5;0.75;1", values: "0;0;10;10;10", keySplines: "0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1", begin: "-0.5s" }), _jsx("animate", { attributeName: "cx", repeatCount: "indefinite", dur: "1s", calcMode: "spline", keyTimes: "0;0.25;0.5;0.75;1", values: "16;16;16;50;84", keySplines: "0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1", begin: "-0.5s" })] }), _jsxs("circle", { cx: "16", cy: "50", r: "10", fill: color, children: [_jsx("animate", { attributeName: "r", repeatCount: "indefinite", dur: "1s", calcMode: "spline", keyTimes: "0;0.25;0.5;0.75;1", values: "0;0;10;10;10", keySplines: "0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1", begin: "-0.75s" }), _jsx("animate", { attributeName: "cx", repeatCount: "indefinite", dur: "1s", calcMode: "spline", keyTimes: "0;0.25;0.5;0.75;1", values: "16;16;16;50;84", keySplines: "0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1", begin: "-0.75s" })] })] }) }));
11
- return (_jsx(Chatbubble, { chatbotId: chatbotId, organizationId: organizationId, isLoadingBubble: true, customStyles: customStyles, theme: theme, Components: Components, message: Components?.LoadingIndicator ? (_jsx(Components.LoadingIndicator, {})) : (defaultLoadingIndicator), role: MessageRole.ASSISTANT, messages: [], postSessionMessage: () => { }, id: "__loading__", setMessages: () => { }, setChatbotConversationId: () => { }, setCanSendMessage: () => { }, setIsChatLoading: () => { } }));
11
+ return (_jsx(Chatbubble, { chatbotId: chatbotId, organizationId: organizationId, isLoadingBubble: true, customStyles: customStyles, theme: theme, Components: Components, message: Components?.LoadingIndicator ? (_jsx(Components.LoadingIndicator, {})) : (defaultLoadingIndicator), role: MessageRole.ASSISTANT, messages: [], postSessionMessage: () => { }, id: "__loading__", setMessages: () => { }, setChatbotConversationRef: () => { }, setCanSendMessage: () => { }, setIsChatLoading: () => { } }));
12
12
  };
13
13
  export default LoadingBubble;
@@ -1,10 +1,10 @@
1
1
  declare const chatbot: {
2
- patchChatbotConversationMemory: (organizationId: number, chatbotId: number, chatbotConversationId: number) => string;
3
- deleteChatbotConversationMemory: (organizationId: number, chatbotId: number, chatbotConversationId: number, memoryKeyToDelete: string) => string;
2
+ patchChatbotConversationMemory: (organizationId: number, chatbotId: number, chatbotConversationRef: string) => string;
3
+ deleteChatbotConversationMemory: (organizationId: number, chatbotId: number, chatbotConversationRef: string, memoryKeyToDelete: string) => string;
4
4
  getChatBotConversationsList: ({ organizationId, chatbotId, conversationIds, }: {
5
5
  organizationId: number;
6
6
  chatbotId: number;
7
- conversationIds: number[];
7
+ conversationIds: string[];
8
8
  }) => string;
9
9
  };
10
10
  export { chatbot };
@@ -1,6 +1,6 @@
1
1
  const chatbot = {
2
- patchChatbotConversationMemory: (organizationId, chatbotId, chatbotConversationId) => `/organizations/${organizationId}/chatbots/${chatbotId}/conversations/${chatbotConversationId}/memory`,
3
- deleteChatbotConversationMemory: (organizationId, chatbotId, chatbotConversationId, memoryKeyToDelete) => `/organizations/${organizationId}/chatbots/${chatbotId}/conversations/${chatbotConversationId}/memory/${memoryKeyToDelete}`,
2
+ patchChatbotConversationMemory: (organizationId, chatbotId, chatbotConversationRef) => `/organizations/${organizationId}/chatbots/${chatbotId}/conversations/${chatbotConversationRef}/memory`,
3
+ deleteChatbotConversationMemory: (organizationId, chatbotId, chatbotConversationRef, memoryKeyToDelete) => `/organizations/${organizationId}/chatbots/${chatbotId}/conversations/${chatbotConversationRef}/memory/${memoryKeyToDelete}`,
4
4
  getChatBotConversationsList: ({ organizationId, chatbotId, conversationIds, }) => {
5
5
  const ids = Array.isArray(conversationIds)
6
6
  ? conversationIds.join(",")
@@ -0,0 +1,130 @@
1
+ /// <reference types="react" />
2
+ import { ChatbotConversation, Message, CMNDChatMemory, CMNDChatbotUITool, ConversationDataObject, ToolDetails } from "../type.js";
3
+ /**
4
+ * Options for configuring the useCMNDChat hook.
5
+ */
6
+ export interface UseCMNDChatOptions {
7
+ /** The unique identifier for the chatbot. */
8
+ chatbotId: number;
9
+ /** The unique identifier for the organization. */
10
+ organizationId: number;
11
+ /** The base URL for the CMND API. */
12
+ baseUrl: string;
13
+ /** Optional API key for authentication. If provided, it will be sent in the 'x-api-key' header. */
14
+ apiKey?: string;
15
+ /** Optional key used for local message persistence. Defaults to a combined string of orgId and chatbotId. */
16
+ chatHistoryStorageKey?: string;
17
+ /** Initial memory/context to send when starting a new conversation. */
18
+ initialMemory?: CMNDChatMemory;
19
+ /** Array of custom UI tools that the AI can call. */
20
+ UITools?: CMNDChatbotUITool[];
21
+ /** Callback triggered whenever new data (chunks or finalized messages) is received from the stream. */
22
+ onData?: (data: ConversationDataObject) => void;
23
+ /**
24
+ * Callback triggered whenever the AI initiates a tool call.
25
+ *
26
+ * For **backend tools**: The hook automatically confirms them, which triggers your backend server
27
+ * to execute the tool and return the output. Use this callback for logging or UI updates.
28
+ *
29
+ * For **UI tools**: You must execute the tool in your frontend, then call submitToolResult with the output.
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * onToolCall: async (toolDetails) => {
34
+ * if (toolDetails.name === 'show_ui_component') {
35
+ * // UI tool - execute in frontend
36
+ * displayComponent(toolDetails.args);
37
+ * submitToolResult('Component displayed');
38
+ * }
39
+ * // Backend tools are handled automatically by the server
40
+ * }
41
+ * ```
42
+ */
43
+ onToolCall?: (toolCall: ToolDetails) => void;
44
+ /**
45
+ * Whether to clean the AI response by removing markdown characters.
46
+ * If true, assistant messages will be returned as plaintext.
47
+ * @default false
48
+ */
49
+ cleanResponse?: boolean;
50
+ }
51
+ /**
52
+ * The object returned by the useCMNDChat hook.
53
+ */
54
+ export interface UseCMNDChatResult {
55
+ /** The list of messages in the current active conversation thread. */
56
+ messages: Message[];
57
+ /** A setter function for the messages list. */
58
+ setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
59
+ /** The current text value of the chat input field. */
60
+ input: string;
61
+ /** A setter function for the chat input field. */
62
+ setInput: React.Dispatch<React.SetStateAction<string>>;
63
+ /** Indicates if a message is currently being processed or streamed. */
64
+ isChatLoading: boolean;
65
+ /** Indicates if the user is allowed to send a message (e.g., not loading, not empty). */
66
+ canSendMessage: boolean;
67
+ /**
68
+ * Sends a message to the chatbot.
69
+ * @param text Optional text to send. If not provided, it uses the current 'input' state.
70
+ * @param onData Optional callback for this specific message stream.
71
+ */
72
+ sendMessage: (text?: string, onData?: (data: ConversationDataObject) => void) => Promise<void>;
73
+ /**
74
+ * Submits the result of a tool call back to the AI.
75
+ * @param toolOutput The string result of the tool execution.
76
+ * @param onData Optional callback for the resulting message stream.
77
+ */
78
+ submitToolResult: (toolOutput: string, onData?: (data: ConversationDataObject) => void) => Promise<void>;
79
+ /** The reference ID for the current active conversation. */
80
+ chatbotConversationRef: string | undefined;
81
+ /** A list of all historical conversations for the current chatbot/org. */
82
+ conversations: ChatbotConversation[];
83
+ /** The currently selected conversation object from history. */
84
+ selectedConversation: ChatbotConversation | null;
85
+ /** Resets the chat state and prepares for a new conversation thread. */
86
+ handleNewChat: () => void;
87
+ /**
88
+ * Switches to an existing conversation from history.
89
+ * @param conversation The conversation object to load.
90
+ */
91
+ handleConversationSelect: (conversation: ChatbotConversation) => void;
92
+ /**
93
+ * Deletes a conversation from history and local storage.
94
+ * @param conversationId The ID of the conversation to delete.
95
+ */
96
+ handleDeleteConversation: (conversationId: string) => Promise<void>;
97
+ /** Re-fetches the list of historical conversations. */
98
+ refreshConversations: () => Promise<void>;
99
+ /** Combined list of backend tools (from API) and UI tools (provided in options). */
100
+ tools: any[];
101
+ /** Holds any error message encountered during API calls. */
102
+ error: string | null;
103
+ }
104
+ /**
105
+ * A comprehensive hook to manage CMND.AI chatbot logic without being forced to use the default UI.
106
+ * This hook handles conversation state, message sending (including streaming), history management, and tool call orchestration.
107
+ *
108
+ * @example
109
+ * ```tsx
110
+ * const { messages, sendMessage, input, setInput, submitToolResult } = useCMNDChat({
111
+ * chatbotId: 1,
112
+ * organizationId: 1,
113
+ * baseUrl: 'https://api.cmnd.ai',
114
+ * cleanResponse: true, // Optional: Returns assistant messages as plaintext
115
+ * onToolCall: async (toolDetails) => {
116
+ * // Backend tools are auto-confirmed by the hook
117
+ * if (toolDetails.name === 'get_playlists') {
118
+ * console.log('Fetching playlists from backend...');
119
+ * }
120
+ *
121
+ * // UI tools need manual execution and confirmation
122
+ * if (toolDetails.name === 'show_notification') {
123
+ * showNotification(toolDetails.args.message);
124
+ * submitToolResult('Notification displayed');
125
+ * }
126
+ * }
127
+ * });
128
+ * ```
129
+ */
130
+ export declare const useCMNDChat: (options: UseCMNDChatOptions) => UseCMNDChatResult;