@navsi.ai/sdk 1.0.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/README.md ADDED
@@ -0,0 +1,348 @@
1
+ # @navsi/sdk - Navsi AI Chatbot SDK
2
+
3
+ AI-powered chatbot SDK for websites with Ask & Navigate modes.
4
+
5
+ > ⚠️ **Note**: This package is part of the `navsi-integrated` monorepo.
6
+
7
+ ## Installation (for external users)
8
+
9
+ ```bash
10
+ npm install @navsi/sdk
11
+ # or
12
+ yarn add @navsi/sdk
13
+ # or
14
+ pnpm add @navsi/sdk
15
+ ```
16
+
17
+ For **Next.js** projects, ensure `next` is installed (optional peer dependency):
18
+ `pnpm add next` (or use your existing Next.js app).
19
+
20
+ ## Quick Start
21
+
22
+ ```tsx
23
+ import { ChatbotProvider, ChatbotWidget } from '@navsi/sdk';
24
+
25
+ function App() {
26
+ return (
27
+ <ChatbotProvider
28
+ apiKey="YOUR_API_KEY"
29
+ serverUrl="wss://your-server.com/ws"
30
+ >
31
+ <YourApp />
32
+ <ChatbotWidget />
33
+ </ChatbotProvider>
34
+ );
35
+ }
36
+ ```
37
+
38
+ ### With Configuration Fetching
39
+
40
+ For a complete setup with widget configuration from your server:
41
+
42
+ ```tsx
43
+ import React, { useState, useEffect } from 'react';
44
+ import { ChatbotProvider, ChatbotWidget } from '@navsi/sdk';
45
+ import type { FlatWidgetConfig } from '@navsi/shared';
46
+
47
+ function App() {
48
+ const [widgetConfig, setWidgetConfig] = useState<FlatWidgetConfig | null>(null);
49
+ const [configError, setConfigError] = useState<string | null>(null);
50
+
51
+ const API_KEY = import.meta.env.VITE_NAVSI_API_KEY || process.env.REACT_APP_NAVSI_API_KEY;
52
+ const API_BASE = import.meta.env.VITE_NAVSI_API_URL || process.env.REACT_APP_NAVSI_API_URL || 'https://api.example.com';
53
+
54
+ // Convert HTTP URL to WebSocket URL
55
+ const getWebSocketUrl = (httpUrl: string): string => {
56
+ const url = new URL(httpUrl);
57
+ const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
58
+ return `${wsProtocol}//${url.host}${url.pathname.replace(/\/$/, '')}/ws`;
59
+ };
60
+ const WS_URL = getWebSocketUrl(API_BASE);
61
+
62
+ useEffect(() => {
63
+ fetch(`${API_BASE}/api/sdk/config`, {
64
+ headers: { 'x-api-key': API_KEY },
65
+ })
66
+ .then((r) => {
67
+ if (!r.ok) throw new Error(`Failed to fetch config: ${r.status}`);
68
+ return r.json();
69
+ })
70
+ .then((data) => {
71
+ if (data?.config && typeof data.config === 'object') {
72
+ setWidgetConfig(data.config as FlatWidgetConfig);
73
+ }
74
+ })
75
+ .catch((err) => {
76
+ console.error('Failed to load widget config:', err);
77
+ setConfigError(err.message);
78
+ // Widget will still work with default config
79
+ });
80
+ }, []);
81
+
82
+ return (
83
+ <ChatbotProvider
84
+ apiKey={API_KEY}
85
+ serverUrl={WS_URL}
86
+ config={widgetConfig}
87
+ >
88
+ <YourApp />
89
+ <ChatbotWidget />
90
+ </ChatbotProvider>
91
+ );
92
+ }
93
+ ```
94
+
95
+ ### Next.js (App Router)
96
+
97
+ Use a **Client Component** to wrap your app with the chatbot and provide a Next.js navigation adapter so the AI can navigate between pages:
98
+
99
+ 1. Create a client component (e.g. `app/ClientProviders.tsx`) with `'use client'` at the top.
100
+ 2. Use `useRouter()` and `usePathname()` from `next/navigation`, and `useNextRouterAdapter(router, pathname)` from `@navsi/sdk`.
101
+ 3. Wrap your app in `ChatbotProvider` (with `navigationAdapter`) and render `ChatbotWidget`.
102
+ 4. Set `NEXT_PUBLIC_NAVSI_API_KEY` and `NEXT_PUBLIC_NAVSI_API_URL` in `.env.local` (WebSocket URL is derived from the API URL).
103
+
104
+ ```tsx
105
+ // app/ClientProviders.tsx
106
+ 'use client';
107
+
108
+ import { useRouter, usePathname } from 'next/navigation';
109
+ import { ChatbotProvider, ChatbotWidget, useNextRouterAdapter } from '@navsi/sdk';
110
+
111
+ function getWebSocketUrl(httpUrl: string): string {
112
+ const url = new URL(httpUrl);
113
+ const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
114
+ return `${wsProtocol}//${url.host}${url.pathname.replace(/\/$/, '')}/ws`;
115
+ }
116
+
117
+ export function ClientProviders({ children }: { children: React.ReactNode }) {
118
+ const router = useRouter();
119
+ const pathname = usePathname();
120
+ const adapter = useNextRouterAdapter(router, pathname);
121
+
122
+ const apiKey = process.env.NEXT_PUBLIC_NAVSI_API_KEY ?? '';
123
+ const apiUrl = process.env.NEXT_PUBLIC_NAVSI_API_URL ?? 'http://localhost:3001';
124
+ const serverUrl = getWebSocketUrl(apiUrl);
125
+
126
+ return (
127
+ <ChatbotProvider apiKey={apiKey} serverUrl={serverUrl} navigationAdapter={adapter} routes={['/', '/products', '/cart']}>
128
+ {children}
129
+ <ChatbotWidget />
130
+ </ChatbotProvider>
131
+ );
132
+ }
133
+ ```
134
+
135
+ In your root `app/layout.tsx`, wrap your app with `<ClientProviders>{children}</ClientProviders>` (or nest it inside your layout so the widget is available on all pages).
136
+
137
+ ## Features
138
+
139
+ ### Ask Mode
140
+ - Natural language Q&A about your website
141
+ - Context-aware responses based on current page
142
+ - Powered by Gemini AI
143
+
144
+ ### Navigate Mode
145
+ - AI-guided navigation through your website
146
+ - Automatic form filling
147
+ - Multi-step task completion
148
+
149
+ ## Configuration Options
150
+
151
+ ```typescript
152
+ interface ChatbotProviderProps {
153
+ // Required
154
+ apiKey: string; // Your API key from the admin dashboard
155
+ serverUrl: string; // WebSocket server URL (e.g., 'wss://api.example.com/ws')
156
+
157
+ // Optional
158
+ config?: FlatWidgetConfig | null; // Widget config fetched from /api/sdk/config
159
+ options?: Partial<WidgetConfig>; // Additional widget configuration (e.g. voiceLanguage: 'hi-IN')
160
+ navigationAdapter?: NavigationAdapter; // Custom navigation adapter (defaults to memory)
161
+ serverActions?: ServerAction[]; // Server-side actions the AI can execute
162
+ routes?: string[]; // List of available routes (for AI context)
163
+ debug?: boolean; // Enable debug logging
164
+ autoConnect?: boolean; // Auto-connect WebSocket on mount (default: true)
165
+ children: React.ReactNode; // Your app components
166
+ }
167
+ ```
168
+
169
+ ### Widget Configuration
170
+
171
+ The `config` prop accepts a flat widget configuration object fetched from your server:
172
+
173
+ ```typescript
174
+ interface FlatWidgetConfig {
175
+ headerTitle?: string;
176
+ welcomeMessage?: string;
177
+ inputPlaceholder?: string;
178
+ showModeToggle?: boolean;
179
+ defaultMode?: 'ask' | 'navigate';
180
+ defaultOpen?: boolean;
181
+ /** BCP-47 language for voice input, output, and AI responses (e.g. 'hi-IN' for Hindi) */
182
+ voiceLanguage?: string;
183
+ theme?: {
184
+ primaryColor?: string;
185
+ secondaryColor?: string;
186
+ backgroundColor?: string;
187
+ textColor?: string;
188
+ fontFamily?: string;
189
+ borderRadius?: number;
190
+ darkMode?: boolean;
191
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
192
+ };
193
+ }
194
+ ```
195
+
196
+ ### Voice language (e.g. Hindi)
197
+
198
+ Set `voiceLanguage` to a BCP-47 locale (e.g. `'hi-IN'` for Hindi) to:
199
+
200
+ - Use that language for **speech recognition** (mic input)
201
+ - Use that language for **speech synthesis** (AI reply read aloud)
202
+ - Have the AI **respond in that language** (e.g. Hindi in Devanagari)
203
+
204
+ Example:
205
+
206
+ ```tsx
207
+ <ChatbotProvider
208
+ apiKey={API_KEY}
209
+ serverUrl={WS_URL}
210
+ options={{ voiceLanguage: 'hi-IN' }}
211
+ >
212
+ <ChatbotWidget />
213
+ </ChatbotProvider>
214
+ ```
215
+
216
+ You can also pass `voiceLanguage` in the `config` object from your API. Browser support for Hindi (and other locales) depends on the client; Chrome supports `hi-IN` for both recognition and synthesis.
217
+
218
+ ## Server Actions
219
+
220
+ Register server-side actions that the AI can execute:
221
+
222
+ ```tsx
223
+ const serverActions = [
224
+ {
225
+ id: 'add-to-cart',
226
+ name: 'Add to Cart',
227
+ description: 'Add a product to the shopping cart',
228
+ parameters: [
229
+ { name: 'productId', type: 'string', required: true },
230
+ { name: 'quantity', type: 'number', required: false, defaultValue: 1 },
231
+ ],
232
+ handler: async (params, context) => {
233
+ // Your logic here
234
+ return { success: true, data: { message: 'Added to cart!' } };
235
+ },
236
+ },
237
+ ];
238
+
239
+ <ChatbotProvider
240
+ apiKey="YOUR_API_KEY"
241
+ serverUrl="wss://your-server.com/ws"
242
+ serverActions={serverActions}
243
+ >
244
+ ```
245
+
246
+ ## Hooks
247
+
248
+ ### useChatbot
249
+
250
+ Access chatbot state and controls:
251
+
252
+ ```tsx
253
+ import { useChatbot } from '@navsi/sdk';
254
+
255
+ function MyComponent() {
256
+ const {
257
+ isConnected,
258
+ mode,
259
+ setMode,
260
+ sendMessage,
261
+ messages
262
+ } = useChatbot();
263
+ }
264
+ ```
265
+
266
+ ### useWebSocket
267
+
268
+ Access WebSocket connection state:
269
+
270
+ ```tsx
271
+ import { useWebSocket } from '@navsi/sdk';
272
+
273
+ function ConnectionStatus() {
274
+ const { isConnected, isReconnecting } = useWebSocket();
275
+
276
+ return <div>Status: {isConnected ? 'Connected' : isReconnecting ? 'Reconnecting' : 'Disconnected'}</div>;
277
+ }
278
+ ```
279
+
280
+ ### useActionExecution
281
+
282
+ Track action execution progress:
283
+
284
+ ```tsx
285
+ import { useActionExecution } from '@navsi/sdk';
286
+
287
+ function ProgressBar() {
288
+ const { progress } = useActionExecution();
289
+
290
+ return progress ? (
291
+ <div>Step {progress.current + 1} of {progress.total}</div>
292
+ ) : null;
293
+ }
294
+ ```
295
+
296
+ ## Environment Variables
297
+
298
+ For production deployments, use environment variables:
299
+
300
+ ```bash
301
+ # Vite (recommended)
302
+ VITE_NAVSI_API_KEY=your_api_key_here
303
+ VITE_NAVSI_API_URL=https://api.example.com
304
+
305
+ # Create React App
306
+ REACT_APP_NAVSI_API_KEY=your_api_key_here
307
+ REACT_APP_NAVSI_API_URL=https://api.example.com
308
+
309
+ # Next.js
310
+ NEXT_PUBLIC_NAVSI_API_KEY=your_api_key_here
311
+ NEXT_PUBLIC_NAVSI_API_URL=https://api.example.com
312
+ ```
313
+
314
+ **Important**: Never commit API keys to version control. Use environment variables or secure configuration services.
315
+
316
+ ## Troubleshooting
317
+
318
+ ### Widget doesn't connect
319
+
320
+ 1. Check that `serverUrl` is correct (use `wss://` for HTTPS, `ws://` for HTTP)
321
+ 2. Verify your API key is valid
322
+ 3. Check browser console for WebSocket connection errors
323
+ 4. Ensure CORS is configured on your server
324
+
325
+ ### Configuration not loading
326
+
327
+ 1. Verify the `/api/sdk/config` endpoint returns valid JSON
328
+ 2. Check that the `x-api-key` header is included in the request
329
+ 3. Widget will fall back to default config if fetch fails
330
+
331
+ ### Actions not working
332
+
333
+ 1. Ensure `navigationAdapter` is provided if using React Router or similar
334
+ 2. Check that DOM elements have proper `data-chatbot-action` attributes
335
+ 3. Enable `debug={true}` to see detailed logs
336
+
337
+ ## Development
338
+
339
+ ```bash
340
+ # From monorepo root
341
+ pnpm --filter @navsi/sdk dev # Watch mode
342
+ pnpm --filter @navsi/sdk build # Build
343
+ pnpm --filter @navsi/sdk lint # Lint
344
+ ```
345
+
346
+ ## License
347
+
348
+ MIT
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-427NHGTX.js.map
3
+ //# sourceMappingURL=chunk-427NHGTX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-427NHGTX.js"}
@@ -0,0 +1,77 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ // src/context/chatbot-context.tsx
4
+ var ChatbotContext = createContext(null);
5
+ function useChatbotContext() {
6
+ const context = useContext(ChatbotContext);
7
+ if (!context) {
8
+ throw new Error("useChatbotContext must be used within a ChatbotProvider");
9
+ }
10
+ return context;
11
+ }
12
+
13
+ // src/hooks/useChatbot.ts
14
+ function useChatbot() {
15
+ const context = useChatbotContext();
16
+ return {
17
+ widgetConfig: context.widgetConfig,
18
+ voiceLanguage: context.voiceLanguage,
19
+ setVoiceLanguage: context.setVoiceLanguage,
20
+ // Messages
21
+ messages: context.messages,
22
+ sendMessage: context.sendMessage,
23
+ clearMessages: context.clearMessages,
24
+ // Mode
25
+ mode: context.mode,
26
+ setMode: context.setMode,
27
+ // Widget visibility
28
+ isWidgetOpen: context.isWidgetOpen,
29
+ setWidgetOpen: context.setWidgetOpen,
30
+ // Connection
31
+ isConnected: context.isConnected,
32
+ connect: context.connect,
33
+ disconnect: context.disconnect,
34
+ // Actions
35
+ executeAction: context.executeAction,
36
+ registerServerAction: context.registerServerAction,
37
+ stopExecution: context.stopExecution,
38
+ // State
39
+ isExecuting: context.isExecuting,
40
+ error: context.error,
41
+ clearError: context.clearError
42
+ };
43
+ }
44
+
45
+ // src/hooks/useActionExecution.ts
46
+ function useActionExecution() {
47
+ const context = useChatbotContext();
48
+ const progress = context.executionState ? {
49
+ current: context.executionState.currentIndex,
50
+ total: context.executionState.totalCommands,
51
+ percentage: context.executionState.totalCommands > 0 ? Math.round(context.executionState.currentIndex / context.executionState.totalCommands * 100) : 0,
52
+ description: context.executionState.description
53
+ } : null;
54
+ return {
55
+ isExecuting: context.isExecuting,
56
+ executionState: context.executionState,
57
+ currentCommand: context.executionState?.currentCommand,
58
+ progress
59
+ };
60
+ }
61
+
62
+ // src/hooks/useWebSocket.ts
63
+ function useWebSocket() {
64
+ const context = useChatbotContext();
65
+ return {
66
+ connectionState: context.connectionState,
67
+ isConnected: context.connectionState === "connected",
68
+ isConnecting: context.connectionState === "connecting",
69
+ isReconnecting: context.connectionState === "reconnecting",
70
+ connect: context.connect,
71
+ disconnect: context.disconnect
72
+ };
73
+ }
74
+
75
+ export { ChatbotContext, useActionExecution, useChatbot, useChatbotContext, useWebSocket };
76
+ //# sourceMappingURL=chunk-6FUUG5WB.js.map
77
+ //# sourceMappingURL=chunk-6FUUG5WB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context/chatbot-context.tsx","../src/hooks/useChatbot.ts","../src/hooks/useActionExecution.ts","../src/hooks/useWebSocket.ts"],"names":[],"mappings":";;;AA2DO,IAAM,cAAA,GAAiB,cAA0C,IAAI;AAUrE,SAAS,iBAAA,GAAyC;AACrD,EAAA,MAAM,OAAA,GAAU,WAAW,cAAc,CAAA;AAEzC,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA,MAAM,IAAI,MAAM,yDAAyD,CAAA;AAAA,EAC7E;AAEA,EAAA,OAAO,OAAA;AACX;;;ACHO,SAAS,UAAA,GAA+B;AAC3C,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAElC,EAAA,OAAO;AAAA,IACH,cAAc,OAAA,CAAQ,YAAA;AAAA,IACtB,eAAe,OAAA,CAAQ,aAAA;AAAA,IACvB,kBAAkB,OAAA,CAAQ,gBAAA;AAAA;AAAA,IAE1B,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,aAAa,OAAA,CAAQ,WAAA;AAAA,IACrB,eAAe,OAAA,CAAQ,aAAA;AAAA;AAAA,IAGvB,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,SAAS,OAAA,CAAQ,OAAA;AAAA;AAAA,IAGjB,cAAc,OAAA,CAAQ,YAAA;AAAA,IACtB,eAAe,OAAA,CAAQ,aAAA;AAAA;AAAA,IAGvB,aAAa,OAAA,CAAQ,WAAA;AAAA,IACrB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,YAAY,OAAA,CAAQ,UAAA;AAAA;AAAA,IAGpB,eAAe,OAAA,CAAQ,aAAA;AAAA,IACvB,sBAAsB,OAAA,CAAQ,oBAAA;AAAA,IAC9B,eAAe,OAAA,CAAQ,aAAA;AAAA;AAAA,IAGvB,aAAa,OAAA,CAAQ,WAAA;AAAA,IACrB,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,YAAY,OAAA,CAAQ;AAAA,GACxB;AACJ;;;ACpFO,SAAS,kBAAA,GAA+C;AAC3D,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAElC,EAAA,MAAM,QAAA,GAAW,QAAQ,cAAA,GACnB;AAAA,IACE,OAAA,EAAS,QAAQ,cAAA,CAAe,YAAA;AAAA,IAChC,KAAA,EAAO,QAAQ,cAAA,CAAe,aAAA;AAAA,IAC9B,UAAA,EAAY,OAAA,CAAQ,cAAA,CAAe,aAAA,GAAgB,IAC7C,IAAA,CAAK,KAAA,CAAO,OAAA,CAAQ,cAAA,CAAe,YAAA,GAAe,OAAA,CAAQ,cAAA,CAAe,aAAA,GAAiB,GAAG,CAAA,GAC7F,CAAA;AAAA,IACN,WAAA,EAAa,QAAQ,cAAA,CAAe;AAAA,GACxC,GACE,IAAA;AAEN,EAAA,OAAO;AAAA,IACH,aAAa,OAAA,CAAQ,WAAA;AAAA,IACrB,gBAAgB,OAAA,CAAQ,cAAA;AAAA,IACxB,cAAA,EAAgB,QAAQ,cAAA,EAAgB,cAAA;AAAA,IACxC;AAAA,GACJ;AACJ;;;ACxBO,SAAS,YAAA,GAAmC;AAC/C,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAElC,EAAA,OAAO;AAAA,IACH,iBAAiB,OAAA,CAAQ,eAAA;AAAA,IACzB,WAAA,EAAa,QAAQ,eAAA,KAAoB,WAAA;AAAA,IACzC,YAAA,EAAc,QAAQ,eAAA,KAAoB,YAAA;AAAA,IAC1C,cAAA,EAAgB,QAAQ,eAAA,KAAoB,cAAA;AAAA,IAC5C,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,YAAY,OAAA,CAAQ;AAAA,GACxB;AACJ","file":"chunk-6FUUG5WB.js","sourcesContent":["/**\n * Chatbot Context\n * \n * React context for chatbot state and functionality.\n */\n\nimport { createContext, useContext } from 'react';\nimport type {\n Message,\n ChatMode,\n ConnectionState,\n ServerAction,\n ExecutionState,\n WidgetConfig,\n} from '@navsi.ai/shared';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ChatbotContextValue {\n /** Widget styling and copy (from admin / API). Applied by ChatbotWidget. */\n widgetConfig: Partial<WidgetConfig> | null;\n\n // State\n messages: Message[];\n mode: ChatMode;\n connectionState: ConnectionState;\n isExecuting: boolean;\n executionState: ExecutionState | null;\n error: Error | null;\n\n // Widget visibility (persists across navigation)\n isWidgetOpen: boolean;\n setWidgetOpen: (open: boolean) => void;\n\n /** User-selected voice/response language (e.g. 'en-US', 'hi-IN'). Overrides widgetConfig.voiceLanguage when set. */\n voiceLanguage: string | undefined;\n setVoiceLanguage: (lang: string | undefined) => void;\n\n // Actions\n sendMessage: (content: string) => void;\n setMode: (mode: ChatMode) => void;\n executeAction: (actionId: string, params?: Record<string, unknown>) => Promise<unknown>;\n registerServerAction: (action: ServerAction) => void;\n clearMessages: () => void;\n clearError: () => void;\n stopExecution: () => void;\n\n // Connection\n connect: () => void;\n disconnect: () => void;\n isConnected: boolean;\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nexport const ChatbotContext = createContext<ChatbotContextValue | null>(null);\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook to access chatbot context\n * Must be used within ChatbotProvider\n */\nexport function useChatbotContext(): ChatbotContextValue {\n const context = useContext(ChatbotContext);\n\n if (!context) {\n throw new Error('useChatbotContext must be used within a ChatbotProvider');\n }\n\n return context;\n}\n","/**\n * useChatbot Hook\n * \n * Main hook for accessing chatbot functionality.\n * Provides simplified API for common operations.\n */\n\nimport { useChatbotContext } from '../context/chatbot-context.js';\nimport type { ChatMode, ServerAction, Message, WidgetConfig } from '@navsi.ai/shared';\n\nexport interface UseChatbotReturn {\n /** Widget styling/copy from admin (or options). Use in ChatbotWidget. */\n widgetConfig: Partial<WidgetConfig> | null;\n\n /** Effective voice/response language (user-selected or config). Use for STT/TTS and locale. */\n voiceLanguage: string | undefined;\n setVoiceLanguage: (lang: string | undefined) => void;\n\n // Messages\n messages: Message[];\n sendMessage: (content: string) => void;\n clearMessages: () => void;\n\n // Mode\n mode: ChatMode;\n setMode: (mode: ChatMode) => void;\n\n // Widget visibility (persists across navigation)\n isWidgetOpen: boolean;\n setWidgetOpen: (open: boolean) => void;\n\n // Connection\n isConnected: boolean;\n connect: () => void;\n disconnect: () => void;\n\n // Actions\n executeAction: (actionId: string, params?: Record<string, unknown>) => Promise<unknown>;\n registerServerAction: (action: ServerAction) => void;\n stopExecution: () => void;\n\n // State\n isExecuting: boolean;\n error: Error | null;\n clearError: () => void;\n}\n\n/**\n * Main hook for chatbot functionality\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { \n * messages, \n * sendMessage, \n * isConnected,\n * mode,\n * setMode,\n * } = useChatbot();\n * \n * return (\n * <div>\n * <button onClick={() => sendMessage('Hello!')}>\n * Send\n * </button>\n * <button onClick={() => startVoice()}>\n * Start Voice\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useChatbot(): UseChatbotReturn {\n const context = useChatbotContext();\n\n return {\n widgetConfig: context.widgetConfig,\n voiceLanguage: context.voiceLanguage,\n setVoiceLanguage: context.setVoiceLanguage,\n // Messages\n messages: context.messages,\n sendMessage: context.sendMessage,\n clearMessages: context.clearMessages,\n\n // Mode\n mode: context.mode,\n setMode: context.setMode,\n\n // Widget visibility\n isWidgetOpen: context.isWidgetOpen,\n setWidgetOpen: context.setWidgetOpen,\n\n // Connection\n isConnected: context.isConnected,\n connect: context.connect,\n disconnect: context.disconnect,\n\n // Actions\n executeAction: context.executeAction,\n registerServerAction: context.registerServerAction,\n stopExecution: context.stopExecution,\n\n // State\n isExecuting: context.isExecuting,\n error: context.error,\n clearError: context.clearError,\n };\n}\n","/**\n * useActionExecution Hook\n * \n * Hook for monitoring action execution state.\n */\n\nimport { useChatbotContext } from '../context/chatbot-context.js';\nimport type { ExecutionState } from '@navsi.ai/shared';\n\nexport interface UseActionExecutionReturn {\n isExecuting: boolean;\n executionState: ExecutionState | null;\n currentCommand: ExecutionState['currentCommand'] | undefined;\n progress: {\n current: number;\n total: number;\n percentage: number;\n /** Optional human-readable description of the current step */\n description?: string;\n } | null;\n}\n\n/**\n * Hook for monitoring action execution\n */\nexport function useActionExecution(): UseActionExecutionReturn {\n const context = useChatbotContext();\n\n const progress = context.executionState\n ? {\n current: context.executionState.currentIndex,\n total: context.executionState.totalCommands,\n percentage: context.executionState.totalCommands > 0\n ? Math.round((context.executionState.currentIndex / context.executionState.totalCommands) * 100)\n : 0,\n description: context.executionState.description,\n }\n : null;\n\n return {\n isExecuting: context.isExecuting,\n executionState: context.executionState,\n currentCommand: context.executionState?.currentCommand,\n progress,\n };\n}\n","/**\n * useWebSocket Hook\n * \n * Hook for managing WebSocket connection state.\n */\n\nimport { useChatbotContext } from '../context/chatbot-context.js';\nimport type { ConnectionState } from '@navsi.ai/shared';\n\nexport interface UseWebSocketReturn {\n connectionState: ConnectionState;\n isConnected: boolean;\n isConnecting: boolean;\n isReconnecting: boolean;\n connect: () => void;\n disconnect: () => void;\n}\n\n/**\n * Hook for WebSocket connection management\n */\nexport function useWebSocket(): UseWebSocketReturn {\n const context = useChatbotContext();\n\n return {\n connectionState: context.connectionState,\n isConnected: context.connectionState === 'connected',\n isConnecting: context.connectionState === 'connecting',\n isReconnecting: context.connectionState === 'reconnecting',\n connect: context.connect,\n disconnect: context.disconnect,\n };\n}\n"]}