@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 +348 -0
- package/dist/chunk-427NHGTX.js +3 -0
- package/dist/chunk-427NHGTX.js.map +1 -0
- package/dist/chunk-6FUUG5WB.js +77 -0
- package/dist/chunk-6FUUG5WB.js.map +1 -0
- package/dist/chunk-EHZXIZIP.js +3752 -0
- package/dist/chunk-EHZXIZIP.js.map +1 -0
- package/dist/components/index.d.ts +66 -0
- package/dist/components/index.js +4 -0
- package/dist/components/index.js.map +1 -0
- package/dist/hooks/index.d.ts +104 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +286 -0
- package/dist/index.js +182 -0
- package/dist/index.js.map +1 -0
- package/package.json +70 -0
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 @@
|
|
|
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"]}
|