@cmnd-ai/chatbot-react 1.10.0 → 1.14.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.
package/dist/type.d.ts CHANGED
@@ -1,46 +1,62 @@
1
1
  import { CSSProperties } from "react";
2
2
  import { ConversationProps } from "./components/Conversation.js";
3
+ /**
4
+ * Context interface for the CMND Chat system.
5
+ * This is used primarily by the internal provider but can be accessed via useCMNDChatContext.
6
+ */
3
7
  export interface CmndChatContext {
8
+ /** Internal props passed to the conversation view. */
4
9
  props: Partial<ConversationProps>;
5
- /**
6
- * Create a new conversation (resets state, starts a new chat thread)
7
- */
10
+ /** Create a new conversation (resets state, starts a new chat thread). */
8
11
  createNewConversation: () => void;
9
- /**
10
- * Toggle the sidebar open/collapsed state
11
- */
12
+ /** Toggle the sidebar open/collapsed state. */
12
13
  toggleSidebar: () => void;
13
- /**
14
- * Open the sidebar (set collapsed to false)
15
- */
14
+ /** Open the sidebar (set collapsed to false). */
16
15
  openSidePanel: () => void;
17
- /**
18
- * Close the sidebar (set collapsed to true)
19
- */
16
+ /** Close the sidebar (set collapsed to true). */
20
17
  closeSidePanel: () => void;
21
- /**
22
- * Set the message text in the input box
23
- */
18
+ /** Set the message text in the input box. */
24
19
  setMessageText: (text: string) => void;
25
- /**
26
- * Send the current message, or set and send if text is provided
27
- */
20
+ /** Send the current message, or set and send if text is provided. */
28
21
  sendMessage: (text?: string) => void;
22
+ /** The socket instance. */
23
+ socket: any | null;
24
+ /** Whether the socket is connected. */
25
+ isConnected: boolean;
29
26
  }
27
+ /**
28
+ * Props for a custom input field component.
29
+ */
30
30
  export interface InputFieldProps {
31
+ /** The current input text. */
31
32
  input: string;
33
+ /** Setter for the input text. */
32
34
  setInput: (input: string) => void;
35
+ /** Whether the send button should be enabled. */
33
36
  canSendMessage: boolean;
37
+ /** Callback to trigger the send action. */
34
38
  handleSendClick: () => void;
35
- inputRef?: React.RefObject<HTMLInputElement> | React.RefObject<HTMLTextAreaElement> | React.RefObject<HTMLTextAreaElement>;
39
+ /** Ref for the input element. */
40
+ inputRef?: React.RefObject<HTMLInputElement> | React.RefObject<HTMLTextAreaElement>;
36
41
  }
42
+ /**
43
+ * Props for a custom send button component.
44
+ */
37
45
  export interface SendButtonProps {
46
+ /** Callback to trigger the send action. */
38
47
  handleSendClick: () => void;
48
+ /** Whether the button should be enabled. */
39
49
  canSendMessage: boolean;
40
50
  }
51
+ /**
52
+ * Utility type for wrapping API responses that might contain an error.
53
+ */
41
54
  export type ErrorOrData<T> = {
42
55
  error: unknown;
43
56
  } | T;
57
+ /**
58
+ * Represents a conversation object from the server.
59
+ */
44
60
  export interface Conversation {
45
61
  conversationId: number;
46
62
  conversationTitle: string;
@@ -50,35 +66,54 @@ export interface Conversation {
50
66
  costLimit: number;
51
67
  systemPrompt: string;
52
68
  enabledTools: any[];
53
- /** Date string format */
69
+ /** Date string format (UTC). */
54
70
  createdAt: string;
55
- /** Date string format */
71
+ /** Date string format (UTC). */
56
72
  updatedAt: string;
57
73
  }
74
+ /**
75
+ * Data object received via streaming or finalized responses.
76
+ */
58
77
  export interface ConversationDataObject {
78
+ /** Indicates if the AI has finished generating the response text. */
59
79
  completionFinished: boolean;
80
+ /** Indicates if this is the final message containing usage metadata. */
60
81
  finalResponseWithUsageData: boolean;
82
+ /** The message text (full or chunk). */
61
83
  message?: string;
84
+ /** The conversation reference ID. */
62
85
  chatbotConversationRef?: string;
86
+ /** Alias for chatbotConversationRef used in some stream responses. */
87
+ conversationRef?: string;
88
+ /** Total tokens used in the conversation so far. */
63
89
  totalTokens?: number;
90
+ /** Total cost of the conversation so far. */
64
91
  totalCost?: number;
92
+ /** Updated list of all messages in the conversation. */
65
93
  messages?: Message[];
94
+ /** Indicates if an error occurred during streaming. */
95
+ hasError?: boolean;
96
+ /** Path associated with the error if available. */
97
+ errorPath?: string[] | string;
98
+ /** Indicates if a function call is currently being streamed. */
99
+ streamingFunctionCall?: boolean;
100
+ /** Name of the function being called. */
101
+ functionName?: string;
102
+ /** Result of a function execution. */
103
+ functionResult?: any;
66
104
  }
67
- interface ToolArgument {
68
- type: string;
69
- description: string;
70
- default?: any;
71
- }
72
- interface ToolArguments {
73
- type: string;
74
- default?: any;
75
- properties: Record<string, ToolArgument>;
76
- required?: string[];
77
- }
105
+ /**
106
+ * Defines the type of tool function.
107
+ */
78
108
  export declare enum FunctionType {
109
+ /** Tool that renders a React component in the chat. */
79
110
  UI = "ui",
111
+ /** Tool that runs on the backend. */
80
112
  BACKEND = "backend"
81
113
  }
114
+ /**
115
+ * Metadata for a tool.
116
+ */
82
117
  export type ToolData = {
83
118
  name: string;
84
119
  description: string;
@@ -87,62 +122,105 @@ export type ToolData = {
87
122
  subsubcategory?: string;
88
123
  functionType: FunctionType;
89
124
  dangerous: boolean;
90
- arguments: ToolArguments;
91
- };
92
- export type UIFunctionArguments<AIProvidedParams> = {
93
- functionArgs: AIProvidedParams;
94
- previousRunResults?: string;
95
- captureResults: (result: string) => void;
125
+ arguments: any;
96
126
  };
127
+ /**
128
+ * Represents a tool that can be used within the chatbot.
129
+ */
97
130
  export interface CMNDChatbotUITool {
131
+ /** Unique name of the tool. */
98
132
  name: string;
133
+ /** Description of what the tool does. */
99
134
  description: string;
135
+ /** Category for organizational purposes. */
100
136
  category: string;
137
+ /** Subcategory for finer organization. */
101
138
  subcategory?: string;
139
+ /** Indicates if the tool should be treated as dangerous (e.g., requires confirmation). */
102
140
  dangerous?: boolean;
141
+ /** Command aliases that might trigger this tool. */
103
142
  associatedCommands?: string[];
143
+ /** Prerequisites required before this tool can run. */
104
144
  prerequisites?: string[];
145
+ /** JSON Schema for the tool's arguments. */
105
146
  argumentSchema: any;
147
+ /** Whether the tool can be re-run after finishing. */
106
148
  rerun?: boolean;
149
+ /** Whether the tool can be re-run with different parameters. */
107
150
  rerunWithDifferentParameters?: boolean;
151
+ /** Whether the tool requires further user input. */
108
152
  capturesUserInput?: boolean;
153
+ /** Explicitly set to 'ui' for UI-based tools. */
109
154
  functionType?: "ui";
155
+ /** The function implementation to run when the tool is called. */
110
156
  runCmd: (args: {
111
157
  functionArgs?: Record<string, any>;
112
158
  captureResults?: (result: any) => Promise<any>;
113
159
  previousRunResults?: any;
114
160
  }, ref?: React.RefObject<HTMLElement>) => void;
115
161
  }
162
+ /**
163
+ * Roles for different message types.
164
+ */
116
165
  export declare enum MessageRole {
166
+ /** A tool call or result. */
117
167
  FUNCTION = "function",
168
+ /** A message from the user. */
118
169
  USER = "user",
170
+ /** A message from the AI assistant. */
119
171
  ASSISTANT = "assistant",
172
+ /** A system instruction. */
120
173
  SYSTEM = "system"
121
174
  }
122
175
  type MessageRoleExceptFunctions = Exclude<MessageRole, MessageRole.FUNCTION>;
176
+ /**
177
+ * Base message structure.
178
+ */
123
179
  interface GenericMessage {
124
180
  id: string;
181
+ /** Whether the message should be hidden or ignored in some contexts. */
125
182
  unuseful: boolean;
183
+ /** Whether the message is visible to the end user. */
126
184
  hiddenFromUser: boolean;
185
+ /** The text content of the message. */
127
186
  message?: string;
187
+ /** The role of the sender. */
128
188
  role: MessageRoleExceptFunctions;
129
189
  }
190
+ /**
191
+ * Details of a tool call or its execution result.
192
+ */
130
193
  export interface ToolDetails {
194
+ /** Arguments passed by the AI. */
131
195
  args: any;
196
+ /** Name of the tool called. */
132
197
  name: string;
198
+ /** Whether the tool run has been confirmed. */
133
199
  confirmed?: boolean;
200
+ /** Timestamp of when the tool was run. */
134
201
  runAt?: string;
202
+ /** The result/output of the tool execution. */
135
203
  output?: string;
136
204
  }
205
+ /**
206
+ * A message representing a tool call.
207
+ */
137
208
  interface ToolMessage {
138
209
  id: string;
139
210
  unuseful: boolean;
140
211
  hiddenFromUser: boolean;
141
212
  message?: string;
142
213
  role: MessageRole.FUNCTION;
214
+ /** Details about the tool call. */
143
215
  tool: ToolDetails;
144
216
  }
217
+ /**
218
+ * Union type for all possible message types in a conversation.
219
+ */
145
220
  export type Message = GenericMessage | ToolMessage;
221
+ /**
222
+ * CSS properties for customizing various parts of the chatbot UI.
223
+ */
146
224
  export interface CustomStyles {
147
225
  chatAvatarStyle?: CSSProperties;
148
226
  inputStyle?: CSSProperties;
@@ -163,9 +241,15 @@ export interface CustomStyles {
163
241
  dateStyle?: CSSProperties;
164
242
  deleteButtonStyle?: CSSProperties;
165
243
  }
244
+ /**
245
+ * KV store for conversation memory/context.
246
+ */
166
247
  export interface CMNDChatMemory {
167
248
  [key: string]: any;
168
249
  }
250
+ /**
251
+ * Simple message structure used in the ChatbotConversation summary.
252
+ */
169
253
  export interface ChatbotConversationMessage {
170
254
  id?: string;
171
255
  role: "user" | "assistant";
@@ -173,16 +257,30 @@ export interface ChatbotConversationMessage {
173
257
  unuseful: boolean;
174
258
  hiddenFromUser: boolean;
175
259
  }
260
+ /**
261
+ * Full conversation metadata and history.
262
+ */
176
263
  export interface ChatbotConversation {
264
+ /** Unique reference for the conversation. */
177
265
  chatbotConversationRef: string;
266
+ /** Snapshot of message history. */
178
267
  messages: ChatbotConversationMessage[];
268
+ /** ID of the parent chatbot. */
179
269
  chatbotId: number;
270
+ /** Human-readable title for the conversation. */
180
271
  chatbotConversationTitle: string;
272
+ /** Creation timestamp. */
181
273
  createdAt: string;
274
+ /** Last update timestamp. */
182
275
  updatedAt: string;
276
+ /** Cumulative cost of this thread. */
183
277
  totalCostSoFar: number;
278
+ /** Cumulative token count for this thread. */
184
279
  totalTokensSoFar: number;
185
280
  }
281
+ /**
282
+ * Response structure when listing conversations.
283
+ */
186
284
  export interface ChatbotConversationsResponse {
187
285
  chatbotConversations: ChatbotConversation[];
188
286
  }
package/dist/type.js CHANGED
@@ -1,12 +1,24 @@
1
+ /**
2
+ * Defines the type of tool function.
3
+ */
1
4
  export var FunctionType;
2
5
  (function (FunctionType) {
6
+ /** Tool that renders a React component in the chat. */
3
7
  FunctionType["UI"] = "ui";
8
+ /** Tool that runs on the backend. */
4
9
  FunctionType["BACKEND"] = "backend";
5
10
  })(FunctionType = FunctionType || (FunctionType = {}));
11
+ /**
12
+ * Roles for different message types.
13
+ */
6
14
  export var MessageRole;
7
15
  (function (MessageRole) {
16
+ /** A tool call or result. */
8
17
  MessageRole["FUNCTION"] = "function";
18
+ /** A message from the user. */
9
19
  MessageRole["USER"] = "user";
20
+ /** A message from the AI assistant. */
10
21
  MessageRole["ASSISTANT"] = "assistant";
22
+ /** A system instruction. */
11
23
  MessageRole["SYSTEM"] = "system";
12
24
  })(MessageRole = MessageRole || (MessageRole = {}));
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Cleans markdown characters from a string to return plaintext.
3
+ * This is a simple regex-based cleaner that handles common markdown patterns.
4
+ *
5
+ * @param markdown The markdown string to clean.
6
+ * @returns The cleaned plaintext string.
7
+ */
8
+ export declare const cleanMarkdown: (markdown: string) => string;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Cleans markdown characters from a string to return plaintext.
3
+ * This is a simple regex-based cleaner that handles common markdown patterns.
4
+ *
5
+ * @param markdown The markdown string to clean.
6
+ * @returns The cleaned plaintext string.
7
+ */
8
+ export const cleanMarkdown = (markdown) => {
9
+ if (!markdown)
10
+ return "";
11
+ return (markdown
12
+ // Handle bold/italic
13
+ .replace(/(\*\*|__)(.*?)\1/g, "$2")
14
+ .replace(/(\*|_)(.*?)\1/g, "$2")
15
+ // Handle links: [text](url) -> text
16
+ .replace(/\[(.*?)\]\(.*?\)/g, "$1")
17
+ // Handle code blocks
18
+ .replace(/```[\s\S]*?```/g, (match) => {
19
+ return match.replace(/```(\w+)?\n?|```/g, "").trim();
20
+ })
21
+ // Handle inline code
22
+ .replace(/`(.*?)`/g, "$1")
23
+ // Handle headers: # Header -> Header
24
+ .replace(/^#+\s+/gm, "")
25
+ // Handle blockquotes: > quote -> quote
26
+ .replace(/^>\s+/gm, "")
27
+ // Handle horizontal rules
28
+ .replace(/^-{3,}|^\*{3,}|^\_{3,}/gm, "")
29
+ // Handle images: ![alt](url) -> alt
30
+ .replace(/!\[(.*?)\]\(.*?\)/g, "$1"));
31
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmnd-ai/chatbot-react",
3
- "version": "1.10.0",
3
+ "version": "1.14.0",
4
4
  "main": "dist/index.js",
5
5
  "description": "",
6
6
  "type": "module",
@@ -31,12 +31,13 @@
31
31
  "access": "public"
32
32
  },
33
33
  "dependencies": {
34
- "axios": "^1.7.5",
34
+ "axios": "^1.13.1",
35
35
  "react-error-boundary": "^4.0.13",
36
36
  "react-icons": "^5.3.0",
37
37
  "react-markdown": "^8.0.6",
38
38
  "react-syntax-highlighter": "^15.5.0",
39
39
  "remark-gfm": "^3.0.1",
40
+ "socket.io-client": "^4.8.3",
40
41
  "uuid": "^13.0.0"
41
42
  }
42
43
  }
package/readme.dev.md CHANGED
@@ -28,3 +28,52 @@
28
28
  ```
29
29
 
30
30
  This will allow you to test your local changes in another project without publishing to npm.
31
+
32
+ ## Core Hook Implementation (`useCMNDChat`)
33
+
34
+ The `useCMNDChat` hook is designed to be the logic engine of the chatbot. Key implementation details:
35
+
36
+ - **State Management**: Uses native React `useState` for messages, input, and loading states.
37
+ - **Real-time Streaming**: Utilizes `postUserConversation` with a stream reader to process response chunks.
38
+ - **Tool Orchestration**:
39
+ - **Backend Tools**: Automatically confirms tool call by setting `confirmed: true`. This triggers the server to execute the tool and return the actual data.
40
+ - **UI Tools**: Fires the `onToolCall` callback. The developer must execute the tool logic and call `submitToolResult(output)`.
41
+ - **Message Cleaning**: When `cleanResponse: true` is enabled, assistant messages are passed through a `cleanMarkdown` utility to return plaintext.
42
+ - **Persistence**: Automatically saves and loads conversation IDs from `localStorage` based on the `organizationId` and `chatbotId`.
43
+
44
+ ### Tool Call Flow
45
+
46
+ 1. AI generates a `function_call`.
47
+ 2. Hook receives the call and adds a message with `role: "function"` to the state (internally).
48
+ 3. **Internal Behavior:**
49
+ - **Backend Tools**: The hook automatically calls `confirmBackendTool()`. This sends a confirmed message back to the server.
50
+ - **UI Tools**: The hook notifies the developer via `onToolCall`.
51
+ 4. **Execution:**
52
+ - **Backend Tools**: The server receives the confirmation, executes the tool, and returns the real data in the next stream update.
53
+ - **UI Tools**: The developer manually calls `submitToolResult(data)` with the result of the frontend execution.
54
+ 5. The conversation resumes with the tool results included in the history.
55
+
56
+ ### Backend Tool Data Flow
57
+
58
+ ```
59
+ User: "Show my playlists"
60
+
61
+ AI calls: get_playlists() (role: function)
62
+
63
+ Hook auto-confirms: internal confirmBackendTool() (sets confirmed: true)
64
+
65
+ Server executes and returns: { playlists: [...] } (Actual data)
66
+
67
+ AI receives data and responds: "Here are your playlists: ..."
68
+ ```
69
+
70
+ **Note**: `FUNCTION` role messages are filtered out from the `messages` array returned by the hook to keep the UI clean. Only `USER` and `ASSISTANT` messages are exposed.
71
+
72
+ ## Building and Releasing
73
+
74
+ 1. **Build the package:**
75
+ ```sh
76
+ npm run build
77
+ ```
78
+ 2. **Release:**
79
+ This project uses `semantic-release` for automated versioning and npm publishing. Ensure your commit messages follow the [Conventional Commits](https://www.conventionalcommits.org/) specification.