@voxket-ai/voxket-live 1.0.141 โ 1.0.144
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 +1977 -122
- package/dist/components/chat/attachment-message.d.ts +9 -0
- package/dist/components/chat/chat-input-panel.d.ts +11 -0
- package/dist/components/chat/chat-message.d.ts +10 -0
- package/dist/components/chat/default-views.d.ts +5 -0
- package/dist/components/chat/markdown-utils.d.ts +5 -0
- package/dist/components/chat/streaming-text.d.ts +8 -0
- package/dist/components/chat/thinking-indicator.d.ts +6 -0
- package/dist/components/chat/tool-execution-indicator.d.ts +8 -0
- package/dist/components/deep-analysis.d.ts +17 -0
- package/dist/components/widget.d.ts +1 -0
- package/dist/core/client.d.ts +17 -2
- package/dist/examples/test-visualization-event.d.ts +18 -0
- package/dist/examples/visualization-view.d.ts +8 -0
- package/dist/hooks/chat-hooks.d.ts +39 -0
- package/dist/index.cjs +70 -66
- package/dist/index.js +7921 -7713
- package/dist/types/core.d.ts +2 -0
- package/dist/types/tools.d.ts +23 -0
- package/package.json +2 -1
- package/dist/core/sdk.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,196 +1,2051 @@
|
|
|
1
|
-
# Voxket
|
|
1
|
+
# ๐ฏ Voxket Web SDK (`@voxket-ai/voxket-live`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**The Complete AI Agent Integration Solution** - Seamlessly embed voice, video, and chat experiences powered by Voxket AI agents into any web application.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@voxket-ai/voxket-live)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
- Supports audio, video, and text chat interactions with Voxket AI agents.
|
|
9
|
-
- Customizable welcome screen and prompts.
|
|
10
|
-
- Flexible styling and sizing options.
|
|
11
|
-
- Built with LiveKit for real-time communication.
|
|
9
|
+
## ๐ Key Features
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
### ๐ฅ **Multi-Modal AI Interactions**
|
|
12
|
+
- **๐ค Voice Conversations** - Real-time voice chat with AI agents
|
|
13
|
+
- **๐ฌ Text Chat** - Instant messaging with typing indicators and message history
|
|
14
|
+
- **๐น Video Calls** - Face-to-face conversations with video support
|
|
15
|
+
- **๐บ Screen Sharing** - Share your screen with AI agents for enhanced support
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
### ๐จ **Flexible Display Options**
|
|
18
|
+
- **๐ช Widget Mode** - Embedded widget for seamless integration
|
|
19
|
+
- **๐ Popup Mode** - Floating chat bubble with customizable positioning
|
|
20
|
+
- **๐ฅ๏ธ Fullscreen Mode** - Immersive full-screen experience
|
|
21
|
+
- **๐ฑ Responsive Design** - Works perfectly on desktop and mobile
|
|
22
|
+
|
|
23
|
+
### ๐ญ **Rich Theming System**
|
|
24
|
+
- **๐ Dark Theme** - Modern dark interface
|
|
25
|
+
- **โ๏ธ Light Theme** - Clean light interface
|
|
26
|
+
- **๐ Vox Theme** - Custom branded Voxket theme
|
|
27
|
+
- **๐จ Custom Themes** - Create your own themes with full CSS control
|
|
28
|
+
|
|
29
|
+
### โก **Powerful Integration Options**
|
|
30
|
+
|
|
31
|
+
#### ๐ง **1. Simple Widget Integration** (React)
|
|
32
|
+
Perfect for React applications with minimal setup.
|
|
33
|
+
|
|
34
|
+
#### ๐ **2. Client SDK Integration** (Any Framework)
|
|
35
|
+
Use the powerful VoxketClient for programmatic control with vanilla JavaScript, Vue, Angular, or any framework.
|
|
36
|
+
|
|
37
|
+
#### ๐ **3. Advanced React Integration**
|
|
38
|
+
Full React ecosystem with providers, hooks, and compound components.
|
|
39
|
+
|
|
40
|
+
### ๐ ๏ธ **Advanced Features**
|
|
41
|
+
|
|
42
|
+
#### ๐ช **Interactive Components (RPC System)**
|
|
43
|
+
- **๐ฏ Agent-Triggered UI** - Agents can display custom React components
|
|
44
|
+
- **๐ Forms & Surveys** - Collect user input through interactive forms
|
|
45
|
+
- **๐ Data Visualization** - Show charts, tables, and rich content
|
|
46
|
+
- **๐ฎ Custom Interactions** - Build any interactive experience
|
|
47
|
+
|
|
48
|
+
#### ๐ **Session Analytics & Logging**
|
|
49
|
+
- **๐ Real-time Metrics** - Monitor session quality and performance
|
|
50
|
+
- **๐ Event Logging** - Track all user interactions and system events
|
|
51
|
+
- **๐พ Data Export** - Export session data for analysis
|
|
52
|
+
- **โฑ๏ธ Session Timers** - Track session duration and activity
|
|
53
|
+
|
|
54
|
+
#### ๐ **Event System**
|
|
55
|
+
- **๐ก Connection Events** - Track connection status and quality
|
|
56
|
+
- **๐ฅ Participant Events** - Monitor who joins and leaves
|
|
57
|
+
- **๐ต Media Events** - Handle track publishing/unpublishing
|
|
58
|
+
- **๐ฌ Message Events** - Real-time message and transcription events
|
|
59
|
+
- **๐ค Agent Events** - Monitor agent state (thinking, speaking, idle)
|
|
60
|
+
|
|
61
|
+
#### ๐๏ธ **Media Controls**
|
|
62
|
+
- **๐ค Microphone Control** - Mute/unmute with visual feedback
|
|
63
|
+
- **๐ท Camera Control** - Enable/disable video with device selection
|
|
64
|
+
- **๐บ Screen Share** - Start/stop screen sharing
|
|
65
|
+
- **๐ง Audio Devices** - Select input/output devices
|
|
66
|
+
- **๐น Video Devices** - Choose camera sources
|
|
67
|
+
|
|
68
|
+
### ๐ผ **Business-Ready Features**
|
|
69
|
+
- **๐ Enterprise Security** - HIPAA-compliant options available
|
|
70
|
+
- **๐ Multi-Language Support** - Internationalization ready
|
|
71
|
+
- **๐ฑ Cross-Platform** - Works on all modern browsers and devices
|
|
72
|
+
- **โก High Performance** - Built on LiveKit for optimal real-time performance
|
|
73
|
+
- **๐ก๏ธ Error Handling** - Robust error recovery and user feedback
|
|
74
|
+
- **๐ Auto-Reconnection** - Automatic connection recovery
|
|
75
|
+
|
|
76
|
+
## ๐ Quick Start
|
|
77
|
+
|
|
78
|
+
### ๐ฆ Installation
|
|
16
79
|
|
|
17
80
|
```bash
|
|
18
81
|
npm install @voxket-ai/voxket-live
|
|
19
82
|
```
|
|
20
|
-
or
|
|
21
83
|
```bash
|
|
22
84
|
yarn add @voxket-ai/voxket-live
|
|
23
85
|
```
|
|
24
86
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
87
|
+
### ๐ฏ **Option 1: Simple Widget (React)**
|
|
88
|
+
|
|
89
|
+
Perfect for React apps - drop in the widget component:
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import React from 'react';
|
|
93
|
+
import VoxketWidget from '@voxket-ai/voxket-live';
|
|
94
|
+
|
|
95
|
+
function App() {
|
|
96
|
+
return (
|
|
97
|
+
<div>
|
|
98
|
+
<h1>My App</h1>
|
|
99
|
+
<VoxketWidget
|
|
100
|
+
agentId="your-agent-id"
|
|
101
|
+
baseUrl="https://your.voxket.api"
|
|
102
|
+
appId="your-app-id"
|
|
103
|
+
appSecret="your-app-secret"
|
|
104
|
+
participantName="User"
|
|
105
|
+
modalities={['voice', 'chat']} // Choose: voice, chat, video, screen_share
|
|
106
|
+
theme="vox" // Options: dark, light, vox
|
|
107
|
+
displayType="widget" // Options: widget, popup, fullscreen
|
|
108
|
+
width="400px"
|
|
109
|
+
height="600px"
|
|
110
|
+
/>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
28
114
|
```
|
|
29
115
|
|
|
30
|
-
|
|
116
|
+
### ๐ง **Option 2: Client SDK (Any Framework)**
|
|
117
|
+
|
|
118
|
+
Use with vanilla JavaScript, Vue, Angular, or any framework:
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
import { VoxketClient } from '@voxket-ai/voxket-live';
|
|
31
122
|
|
|
32
|
-
|
|
123
|
+
// Create client
|
|
124
|
+
const client = new VoxketClient({
|
|
125
|
+
appId: "your-app-id",
|
|
126
|
+
appSecret: "your-app-secret",
|
|
127
|
+
baseUrl: "https://your.voxket.api",
|
|
128
|
+
agentId: "your-agent-id",
|
|
129
|
+
participantName: "User"
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Connect and render UI
|
|
133
|
+
await client.connect();
|
|
134
|
+
client.renderUI({
|
|
135
|
+
target: '#voxket-container', // CSS selector or HTMLElement
|
|
136
|
+
modality: ['voice', 'chat'],
|
|
137
|
+
theme: 'dark',
|
|
138
|
+
displayType: 'widget',
|
|
139
|
+
autoStart: true
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### ๐๏ธ **Option 3: Advanced React Integration**
|
|
144
|
+
|
|
145
|
+
Full React ecosystem with providers and hooks:
|
|
33
146
|
|
|
34
147
|
```tsx
|
|
35
|
-
import
|
|
36
|
-
import VoxketWidget, { VoxketWidgetProps } from '@voxket-ai/voxket-live';
|
|
148
|
+
import { VoxketProvider, useVoxket } from '@voxket-ai/voxket-live';
|
|
37
149
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
150
|
+
function App() {
|
|
151
|
+
return (
|
|
152
|
+
<VoxketProvider config={{
|
|
153
|
+
appId: "your-app-id",
|
|
154
|
+
appSecret: "your-app-secret",
|
|
155
|
+
baseUrl: "https://your.voxket.api"
|
|
156
|
+
}}>
|
|
157
|
+
<MyComponent />
|
|
158
|
+
</VoxketProvider>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function MyComponent() {
|
|
163
|
+
const { client, connect, session } = useVoxket();
|
|
164
|
+
|
|
165
|
+
const handleStartChat = async () => {
|
|
166
|
+
await connect();
|
|
167
|
+
const session = await client.startSession("agent-id", {
|
|
168
|
+
modalities: ['chat'],
|
|
169
|
+
participantName: "User"
|
|
170
|
+
});
|
|
50
171
|
};
|
|
51
172
|
|
|
52
173
|
return (
|
|
53
174
|
<div>
|
|
54
|
-
<
|
|
55
|
-
<p>
|
|
56
|
-
<VoxketWidget {...widgetProps} />
|
|
175
|
+
<button onClick={handleStartChat}>Start Chat</button>
|
|
176
|
+
{session && <p>Session active: {session.id}</p>}
|
|
57
177
|
</div>
|
|
58
178
|
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export default MyCustomApp;
|
|
179
|
+
}
|
|
62
180
|
```
|
|
63
181
|
|
|
64
|
-
|
|
182
|
+
## ๐๏ธ **Display Types**
|
|
65
183
|
|
|
66
|
-
|
|
184
|
+
### ๐ช **Widget Mode**
|
|
185
|
+
Embedded widget that fits naturally into your application:
|
|
67
186
|
|
|
68
|
-
|
|
187
|
+
```tsx
|
|
188
|
+
<VoxketWidget
|
|
189
|
+
displayType="widget"
|
|
190
|
+
width="400px"
|
|
191
|
+
height="600px"
|
|
192
|
+
// ... other props
|
|
193
|
+
/>
|
|
194
|
+
```
|
|
69
195
|
|
|
70
|
-
|
|
196
|
+
### ๐ **Popup Mode**
|
|
197
|
+
Floating chat bubble that can be positioned anywhere:
|
|
71
198
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
| `statusMessage` | `string` | No | `''` | A message to display on the welcome screen, potentially for agent status or custom greetings. |
|
|
82
|
-
| `welcomeTitle` | `string` | No | `''` | Custom title for the widget's welcome screen. |
|
|
83
|
-
| `welcomeSubTitle` | `string` | No | `''` | Custom subtitle for the widget's welcome screen. |
|
|
84
|
-
| `width` | `string` | No | `'w-96'` | Defines the widget width. Accepts Tailwind CSS classes (e.g., `w-96`) or standard CSS values (e.g., `500px`). |
|
|
85
|
-
| `height` | `string` | No | `'h-[25rem]'` | Defines the widget height. Accepts Tailwind CSS classes (e.g., `h-[25rem]`) or CSS values (e.g., `600px`). |
|
|
86
|
-
| `loadingText` | `string` | No | `''` | Text displayed while the session is initializing and connecting. |
|
|
87
|
-
| `suportsChatInput` | `boolean` | No | `true` | Enables or disables the text chat input feature. |
|
|
88
|
-
| `suportsVideoInput` | `boolean` | No | `true` | Enables or disables the user's video input feature. |
|
|
89
|
-
| `suportsScreenShare`| `boolean` | No | `true` | Enables or disables the screen sharing feature for the user. |
|
|
90
|
-
| `theme` | `'dark' \| 'light' \| 'vox'` | No | `'vox'` | Sets the widget's visual theme. |
|
|
91
|
-
| `onSessionStart` | `(sessionId: string) => void` | No | `undefined` | Callback fired when a session starts. Receives the session ID. |
|
|
92
|
-
| `onSessionEnd` | `(metrics: SessionMetrics) => void` | No | `undefined` | Callback fired when a session ends. Receives session metrics. |
|
|
93
|
-
| `enableSessionLogging` | `boolean` | No | `true` | Enables or disables session logging functionality. |
|
|
94
|
-
| `onSessionLogsUpdate` | `(logs: SessionLog[]) => void` | No | `undefined` | Callback fired when session logs are updated. Provides real-time access to session events. |
|
|
95
|
-
| `onSessionMetricsUpdate` | `(metrics: SessionMetrics) => void` | No | `undefined` | Callback fired when session metrics are updated. Provides real-time access to session metrics. |
|
|
199
|
+
```tsx
|
|
200
|
+
<VoxketWidget
|
|
201
|
+
displayType="popup"
|
|
202
|
+
popupPosition="bottom-right" // top-left, top-right, bottom-left, bottom-right
|
|
203
|
+
popupTriggerText="Need Help?"
|
|
204
|
+
onPopupToggle={(isOpen) => console.log('Popup:', isOpen)}
|
|
205
|
+
// ... other props
|
|
206
|
+
/>
|
|
207
|
+
```
|
|
96
208
|
|
|
97
|
-
|
|
209
|
+
### ๐ฅ๏ธ **Fullscreen Mode**
|
|
210
|
+
Immersive full-screen experience:
|
|
98
211
|
|
|
99
|
-
|
|
212
|
+
```tsx
|
|
213
|
+
<VoxketWidget
|
|
214
|
+
displayType="fullscreen"
|
|
215
|
+
onDisplayTypeChange={(type) => console.log('Display changed to:', type)}
|
|
216
|
+
// ... other props
|
|
217
|
+
/>
|
|
218
|
+
```
|
|
100
219
|
|
|
101
|
-
|
|
102
|
-
- **Session View:** Once connected, this view handles the live interaction with the agent, including audio, video (if enabled), and chat.
|
|
103
|
-
- **Device Permissions:** The widget will request microphone and camera permissions as needed when the session starts.
|
|
104
|
-
- **Error Handling:** Basic error messages are displayed for connection issues or media device errors using toast notifications.
|
|
220
|
+
## ๐จ **Themes & Customization**
|
|
105
221
|
|
|
106
|
-
|
|
222
|
+
### ๐ญ **Built-in Themes**
|
|
107
223
|
|
|
108
|
-
|
|
224
|
+
```tsx
|
|
225
|
+
// Dark theme
|
|
226
|
+
<VoxketWidget theme="dark" />
|
|
227
|
+
|
|
228
|
+
// Light theme
|
|
229
|
+
<VoxketWidget theme="light" />
|
|
230
|
+
|
|
231
|
+
// Voxket branded theme
|
|
232
|
+
<VoxketWidget theme="vox" />
|
|
233
|
+
```
|
|
109
234
|
|
|
110
|
-
###
|
|
235
|
+
### ๐จ **Custom Styling**
|
|
111
236
|
|
|
112
237
|
```tsx
|
|
113
|
-
|
|
238
|
+
<VoxketWidget
|
|
239
|
+
className="my-custom-widget"
|
|
240
|
+
width="500px"
|
|
241
|
+
height="700px"
|
|
242
|
+
// Custom CSS classes and dimensions
|
|
243
|
+
/>
|
|
244
|
+
```
|
|
114
245
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
};
|
|
246
|
+
## ๐ฌ **Session Events & Analytics**
|
|
247
|
+
|
|
248
|
+
### ๐ **Basic Session Tracking**
|
|
119
249
|
|
|
120
|
-
|
|
250
|
+
```tsx
|
|
251
|
+
<VoxketWidget
|
|
252
|
+
onSessionStart={(sessionId) => {
|
|
253
|
+
console.log('Session started:', sessionId);
|
|
254
|
+
analytics.track('voxket_session_started', { sessionId });
|
|
255
|
+
}}
|
|
256
|
+
onSessionEnd={(metrics) => {
|
|
121
257
|
console.log('Session ended:', metrics);
|
|
122
|
-
|
|
258
|
+
analytics.track('voxket_session_ended', {
|
|
259
|
+
duration: metrics.duration,
|
|
260
|
+
messageCount: metrics.messageCount
|
|
261
|
+
});
|
|
262
|
+
}}
|
|
263
|
+
enableSessionLogging={true}
|
|
264
|
+
/>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### ๐ **Advanced Session Monitoring**
|
|
268
|
+
|
|
269
|
+
```tsx
|
|
270
|
+
import { SessionLog, SessionMetrics } from '@voxket-ai/voxket-live';
|
|
271
|
+
|
|
272
|
+
function MyApp() {
|
|
273
|
+
const [logs, setLogs] = useState<SessionLog[]>([]);
|
|
274
|
+
const [metrics, setMetrics] = useState<SessionMetrics | null>(null);
|
|
123
275
|
|
|
124
276
|
return (
|
|
125
277
|
<VoxketWidget
|
|
126
|
-
|
|
278
|
+
onSessionLogsUpdate={(logs) => {
|
|
279
|
+
setLogs(logs);
|
|
280
|
+
// Send to your analytics service
|
|
281
|
+
analytics.track('session_events', { eventCount: logs.length });
|
|
282
|
+
}}
|
|
283
|
+
onSessionMetricsUpdate={(metrics) => {
|
|
284
|
+
setMetrics(metrics);
|
|
285
|
+
// Update your dashboard
|
|
286
|
+
updateDashboard(metrics);
|
|
287
|
+
}}
|
|
127
288
|
// ... other props
|
|
128
|
-
onSessionStart={handleSessionStart}
|
|
129
|
-
onSessionEnd={handleSessionEnd}
|
|
130
|
-
enableSessionLogging={true}
|
|
131
289
|
/>
|
|
132
290
|
);
|
|
133
291
|
}
|
|
134
292
|
```
|
|
135
293
|
|
|
136
|
-
|
|
294
|
+
## ๐ช **Interactive Components (RPC System)**
|
|
137
295
|
|
|
138
|
-
|
|
296
|
+
### ๐ **Agent-Triggered UI Components**
|
|
139
297
|
|
|
140
|
-
|
|
141
|
-
|
|
298
|
+
Agents can trigger custom React components during conversations:
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
import { VoxketClient } from '@voxket-ai/voxket-live';
|
|
302
|
+
|
|
303
|
+
const client = new VoxketClient(config);
|
|
304
|
+
|
|
305
|
+
// Register a custom form component
|
|
306
|
+
await client.registerFrontendRPC(
|
|
307
|
+
'customer_survey', // Method name the agent calls
|
|
308
|
+
SurveyComponent, // Your React component
|
|
309
|
+
'modal' // Presentation mode: embedded, modal, fullscreen
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
// Your custom component
|
|
313
|
+
function SurveyComponent({ handler, data }) {
|
|
314
|
+
const [rating, setRating] = useState(0);
|
|
315
|
+
|
|
316
|
+
const handleSubmit = () => {
|
|
317
|
+
handler.didSuccess({
|
|
318
|
+
survey_response: rating,
|
|
319
|
+
feedback: "Great service!"
|
|
320
|
+
});
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
return (
|
|
324
|
+
<div>
|
|
325
|
+
<h3>Rate your experience</h3>
|
|
326
|
+
<StarRating value={rating} onChange={setRating} />
|
|
327
|
+
<button onClick={handleSubmit}>Submit</button>
|
|
328
|
+
<button onClick={handler.dismissView}>Skip</button>
|
|
329
|
+
</div>
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### ๐ฏ **Interactive UI Examples**
|
|
335
|
+
- **๐ Forms & Surveys** - Collect user feedback
|
|
336
|
+
- **๐ Data Visualization** - Show charts and graphs
|
|
337
|
+
- **๐ Product Catalogs** - Display interactive product lists
|
|
338
|
+
- **๐
Appointment Scheduling** - Calendar integrations
|
|
339
|
+
- **๐ณ Payment Flows** - Secure payment processing
|
|
340
|
+
- **๐ฎ Custom Games** - Interactive experiences
|
|
341
|
+
|
|
342
|
+
## ๐ก **Event System**
|
|
343
|
+
|
|
344
|
+
### ๐ **Connection Events**
|
|
345
|
+
|
|
346
|
+
```javascript
|
|
347
|
+
client.on('connection.connected', () => {
|
|
348
|
+
console.log('โ
Connected to Voxket');
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
client.on('connection.disconnected', (reason) => {
|
|
352
|
+
console.log('โ Disconnected:', reason);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
client.on('connection.error', (error) => {
|
|
356
|
+
console.error('๐จ Connection error:', error);
|
|
357
|
+
});
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## ๐ **Custom Event System**
|
|
361
|
+
|
|
362
|
+
### ๐ก **Register Event Emitters**
|
|
363
|
+
|
|
364
|
+
Register custom event emitters to listen for LiveKit text stream topics:
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { VoxketClient } from '@voxket-ai/voxket-live';
|
|
368
|
+
|
|
369
|
+
const client = new VoxketClient(config);
|
|
370
|
+
|
|
371
|
+
// Register an event emitter for custom events
|
|
372
|
+
client.registerEventEmitter('custom_event_topic', (data) => {
|
|
373
|
+
console.log('Custom event received:', data);
|
|
374
|
+
// Handle your custom business logic
|
|
375
|
+
handleCustomEvent(data);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// Register multiple event emitters
|
|
379
|
+
client.registerEventEmitter('user_action', (actionData) => {
|
|
380
|
+
console.log('User action:', actionData);
|
|
381
|
+
analytics.track('user_action', actionData);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
client.registerEventEmitter('system_notification', (notification) => {
|
|
385
|
+
showNotification(notification);
|
|
386
|
+
});
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### ๐ฏ **Event Listener Registration**
|
|
390
|
+
|
|
391
|
+
Register event listeners for any SDK events with automatic cleanup:
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
// Register event listeners with automatic unsubscribe
|
|
395
|
+
const unsubscribe = client.registerEventListener('chat.message.received', (message) => {
|
|
396
|
+
console.log('New message:', message);
|
|
397
|
+
updateUI(message);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// Manual cleanup when needed
|
|
401
|
+
unsubscribe();
|
|
402
|
+
|
|
403
|
+
// Register multiple listeners
|
|
404
|
+
client.registerEventListener('connection.connected', () => {
|
|
405
|
+
console.log('Connected to Voxket!');
|
|
406
|
+
updateConnectionStatus('connected');
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
client.registerEventListener('agent.thinking', () => {
|
|
410
|
+
showTypingIndicator();
|
|
411
|
+
});
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### ๐ข **Business Integration Examples**
|
|
415
|
+
|
|
416
|
+
#### **Real-time Notifications**
|
|
417
|
+
```typescript
|
|
418
|
+
// Listen for agent-triggered notifications
|
|
419
|
+
client.registerEventEmitter('agent_notification', (data) => {
|
|
420
|
+
// Show toast notification
|
|
421
|
+
showToast({
|
|
422
|
+
title: data.title,
|
|
423
|
+
message: data.message,
|
|
424
|
+
type: data.type
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// Listen for system updates
|
|
429
|
+
client.registerEventEmitter('system_update', (updateInfo) => {
|
|
430
|
+
if (updateInfo.type === 'maintenance') {
|
|
431
|
+
showMaintenanceWarning(updateInfo.schedule);
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
#### **Custom Analytics Integration**
|
|
437
|
+
```typescript
|
|
438
|
+
// Track custom business events
|
|
439
|
+
client.registerEventEmitter('business_event', (eventData) => {
|
|
440
|
+
// Send to your analytics platform
|
|
441
|
+
analytics.track(eventData.event_name, {
|
|
442
|
+
...eventData.properties,
|
|
443
|
+
timestamp: new Date().toISOString(),
|
|
444
|
+
session_id: client.getCurrentSession()?.id
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
// Example: Track user interactions
|
|
449
|
+
client.registerEventEmitter('user_interaction', (interaction) => {
|
|
450
|
+
mixpanel.track('Voxket User Interaction', {
|
|
451
|
+
interaction_type: interaction.type,
|
|
452
|
+
interaction_data: interaction.data,
|
|
453
|
+
user_id: getCurrentUserId()
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
#### **Workflow Automation**
|
|
459
|
+
```typescript
|
|
460
|
+
// Trigger business workflows
|
|
461
|
+
client.registerEventEmitter('workflow_trigger', (workflowData) => {
|
|
462
|
+
switch (workflowData.workflow_type) {
|
|
463
|
+
case 'lead_qualification':
|
|
464
|
+
triggerLeadQualificationWorkflow(workflowData.lead_data);
|
|
465
|
+
break;
|
|
466
|
+
case 'support_escalation':
|
|
467
|
+
escalateToHumanAgent(workflowData.ticket_data);
|
|
468
|
+
break;
|
|
469
|
+
case 'appointment_booking':
|
|
470
|
+
processAppointmentRequest(workflowData.appointment_data);
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### ๐ฌ **Chat & Messaging Events**
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
client.on('chat.message.received', (message) => {
|
|
480
|
+
console.log('๐ฌ New message:', message);
|
|
481
|
+
displayMessage(message);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
client.on('chat.message.sent', (message) => {
|
|
485
|
+
console.log('๐ค Message sent:', message);
|
|
486
|
+
logOutgoingMessage(message);
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
client.on('transcription.received', (transcription) => {
|
|
490
|
+
console.log('๐ค Voice transcription:', transcription);
|
|
491
|
+
displayTranscription(transcription);
|
|
492
|
+
});
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### ๐ค **Agent State Events**
|
|
496
|
+
|
|
497
|
+
```javascript
|
|
498
|
+
client.on('agent.thinking', () => {
|
|
499
|
+
showTypingIndicator();
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
client.on('agent.speaking', () => {
|
|
503
|
+
showSpeakingIndicator();
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
client.on('agent.connected', () => {
|
|
507
|
+
console.log('๐ค Agent joined the conversation');
|
|
508
|
+
});
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### ๐ต **Media Events**
|
|
512
|
+
|
|
513
|
+
```javascript
|
|
514
|
+
client.on('track.muted', ({ source, enabled }) => {
|
|
515
|
+
console.log(`๐ ${source} muted:`, !enabled);
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
client.on('track.unmuted', ({ source, enabled }) => {
|
|
519
|
+
console.log(`๐ ${source} unmuted:`, enabled);
|
|
520
|
+
});
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
## ๐๏ธ **Media Controls**
|
|
524
|
+
|
|
525
|
+
### ๐ค **Microphone Control**
|
|
526
|
+
|
|
527
|
+
```javascript
|
|
528
|
+
// Toggle microphone
|
|
529
|
+
await client.toggleMicrophone();
|
|
530
|
+
|
|
531
|
+
// Explicit control
|
|
532
|
+
await client.setMicrophoneEnabled(true); // Unmute
|
|
533
|
+
await client.setMicrophoneEnabled(false); // Mute
|
|
534
|
+
|
|
535
|
+
// Check current state
|
|
536
|
+
const isMuted = !client.isMicrophoneEnabled;
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### ๐ท **Camera Control**
|
|
540
|
+
|
|
541
|
+
```javascript
|
|
542
|
+
// Toggle camera
|
|
543
|
+
await client.toggleCamera();
|
|
544
|
+
|
|
545
|
+
// Explicit control
|
|
546
|
+
await client.enableCamera();
|
|
547
|
+
await client.disableCamera();
|
|
548
|
+
|
|
549
|
+
// Check current state
|
|
550
|
+
const isCameraOn = client.isCameraEnabled;
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### ๐บ **Screen Sharing**
|
|
554
|
+
|
|
555
|
+
```javascript
|
|
556
|
+
// Start screen share
|
|
557
|
+
await client.startScreenShare();
|
|
558
|
+
|
|
559
|
+
// Stop screen share
|
|
560
|
+
await client.stopScreenShare();
|
|
561
|
+
|
|
562
|
+
// Check if screen sharing is active
|
|
563
|
+
const isSharing = client.isScreenShareEnabled;
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### ๐ง **Device Management**
|
|
567
|
+
|
|
568
|
+
```javascript
|
|
569
|
+
// Get available devices
|
|
570
|
+
const audioDevices = await client.getAudioInputDevices();
|
|
571
|
+
const videoDevices = await client.getVideoInputDevices();
|
|
572
|
+
|
|
573
|
+
// Switch devices
|
|
574
|
+
await client.setAudioInputDevice(deviceId);
|
|
575
|
+
await client.setVideoInputDevice(deviceId);
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
## ๐ผ **Business Integration Examples**
|
|
579
|
+
|
|
580
|
+
### ๐ **E-commerce Customer Support**
|
|
581
|
+
|
|
582
|
+
```javascript
|
|
583
|
+
const supportClient = new VoxketClient({
|
|
584
|
+
appId: "ecommerce-app",
|
|
585
|
+
appSecret: "your-secret",
|
|
586
|
+
baseUrl: "https://api.voxket.com",
|
|
587
|
+
agentId: "customer-support",
|
|
588
|
+
|
|
589
|
+
onMessageReceived: (message) => {
|
|
590
|
+
// Log customer interactions
|
|
591
|
+
analytics.track('customer_support_message', {
|
|
592
|
+
content: message.content,
|
|
593
|
+
timestamp: message.timestamp
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
// Add to product pages
|
|
599
|
+
document.getElementById('help-button').onclick = async () => {
|
|
600
|
+
await supportClient.connect();
|
|
601
|
+
supportClient.renderUI({
|
|
602
|
+
target: '#support-widget',
|
|
603
|
+
modality: ['chat'],
|
|
604
|
+
theme: 'light',
|
|
605
|
+
displayType: 'popup',
|
|
606
|
+
popupPosition: 'bottom-right'
|
|
607
|
+
});
|
|
608
|
+
};
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
### ๐ฅ **Healthcare Patient Portal**
|
|
612
|
+
|
|
613
|
+
```javascript
|
|
614
|
+
const healthcareClient = new VoxketClient({
|
|
615
|
+
appId: "healthcare-portal",
|
|
616
|
+
appSecret: "hipaa-compliant-secret",
|
|
617
|
+
baseUrl: "https://secure.voxket.com",
|
|
618
|
+
agentId: "patient-support",
|
|
619
|
+
participantName: getCurrentPatient().name,
|
|
620
|
+
|
|
621
|
+
onSessionStart: (sessionId) => {
|
|
622
|
+
// HIPAA-compliant logging
|
|
623
|
+
auditLogger.log({
|
|
624
|
+
event: 'patient_session_started',
|
|
625
|
+
sessionId,
|
|
626
|
+
patientId: getCurrentPatient().id,
|
|
627
|
+
timestamp: new Date()
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
// Secure patient communications
|
|
633
|
+
await healthcareClient.connect();
|
|
634
|
+
healthcareClient.renderUI({
|
|
635
|
+
target: '#patient-support',
|
|
636
|
+
modality: ['chat'], // Text-only for security
|
|
637
|
+
theme: 'light'
|
|
638
|
+
});
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
### ๐ฐ **Financial Services**
|
|
642
|
+
|
|
643
|
+
```javascript
|
|
644
|
+
const financeClient = new VoxketClient({
|
|
645
|
+
appId: "banking-app",
|
|
646
|
+
appSecret: "secure-secret",
|
|
647
|
+
baseUrl: "https://secure-api.voxket.com",
|
|
648
|
+
agentId: "financial-advisor",
|
|
649
|
+
|
|
650
|
+
onSessionStart: (sessionId) => {
|
|
651
|
+
// Compliance logging
|
|
652
|
+
complianceLogger.record({
|
|
653
|
+
type: 'customer_interaction_start',
|
|
654
|
+
sessionId,
|
|
655
|
+
customerId: getCurrentCustomer().id
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
// Financial consultation widget
|
|
661
|
+
await financeClient.connect();
|
|
662
|
+
financeClient.renderUI({
|
|
663
|
+
target: '#advisor-chat',
|
|
664
|
+
modality: ['voice', 'video'],
|
|
665
|
+
theme: 'dark',
|
|
666
|
+
displayType: 'fullscreen'
|
|
667
|
+
});
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
## ๐ ๏ธ **Advanced Usage**
|
|
671
|
+
|
|
672
|
+
### ๐ **Session Management**
|
|
673
|
+
|
|
674
|
+
```javascript
|
|
675
|
+
// Start a session with specific configuration
|
|
676
|
+
const session = await client.startSession("agent-id", {
|
|
677
|
+
participantName: "John Doe",
|
|
678
|
+
modalities: ['voice', 'chat'],
|
|
679
|
+
metadata: {
|
|
680
|
+
customerType: "premium",
|
|
681
|
+
department: "support"
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
// Get current session
|
|
686
|
+
const currentSession = client.getCurrentSession();
|
|
687
|
+
|
|
688
|
+
// End session manually
|
|
689
|
+
await client.endSession();
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
### ๐ **Custom Analytics Integration**
|
|
693
|
+
|
|
694
|
+
```javascript
|
|
695
|
+
client.on('session.created', (session) => {
|
|
696
|
+
analytics.track('voxket_session_created', {
|
|
697
|
+
sessionId: session.id,
|
|
698
|
+
agentId: session.agentId,
|
|
699
|
+
modalities: session.activeModalities
|
|
700
|
+
});
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
client.on('chat.message.received', (message) => {
|
|
704
|
+
analytics.track('voxket_message_received', {
|
|
705
|
+
messageType: message.sender.type,
|
|
706
|
+
contentLength: message.content.length,
|
|
707
|
+
sessionId: client.getCurrentSession()?.id
|
|
708
|
+
});
|
|
709
|
+
});
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
### ๐ **Multiple Widget Instances**
|
|
713
|
+
|
|
714
|
+
```javascript
|
|
715
|
+
// Support chat
|
|
716
|
+
const supportClient = new VoxketClient(supportConfig);
|
|
717
|
+
supportClient.renderUI({
|
|
718
|
+
target: '#support-widget',
|
|
719
|
+
modality: ['chat']
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
// Sales call
|
|
723
|
+
const salesClient = new VoxketClient(salesConfig);
|
|
724
|
+
salesClient.renderUI({
|
|
725
|
+
target: '#sales-widget',
|
|
726
|
+
modality: ['voice', 'video']
|
|
727
|
+
});
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
## ๐ฏ **HTML/Vanilla JavaScript Integration**
|
|
731
|
+
|
|
732
|
+
Use the SDK without any framework:
|
|
733
|
+
|
|
734
|
+
```html
|
|
735
|
+
<!DOCTYPE html>
|
|
736
|
+
<html>
|
|
737
|
+
<head>
|
|
738
|
+
<title>Voxket Integration</title>
|
|
739
|
+
<script src="https://unpkg.com/@voxket-ai/voxket-live@latest/dist/index.js"></script>
|
|
740
|
+
</head>
|
|
741
|
+
<body>
|
|
742
|
+
<div id="voxket-container"></div>
|
|
743
|
+
|
|
744
|
+
<script>
|
|
745
|
+
const { VoxketClient } = window.VoxketLive;
|
|
746
|
+
|
|
747
|
+
const client = new VoxketClient({
|
|
748
|
+
appId: 'your-app-id',
|
|
749
|
+
appSecret: 'your-secret',
|
|
750
|
+
baseUrl: 'https://api.voxket.com',
|
|
751
|
+
agentId: 'support-agent'
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
client.connect().then(() => {
|
|
755
|
+
client.renderUI({
|
|
756
|
+
target: '#voxket-container',
|
|
757
|
+
modality: ['chat'],
|
|
758
|
+
theme: 'light'
|
|
759
|
+
});
|
|
760
|
+
});
|
|
761
|
+
</script>
|
|
762
|
+
</body>
|
|
763
|
+
</html>
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
## ๐ง **VoxketClient API Reference**
|
|
767
|
+
|
|
768
|
+
### ๐๏ธ **Constructor Options**
|
|
769
|
+
|
|
770
|
+
```typescript
|
|
771
|
+
interface VoxketClientConfig {
|
|
772
|
+
// Required
|
|
773
|
+
appId: string; // Your Voxket App ID
|
|
774
|
+
appSecret: string; // Your Voxket App Secret
|
|
775
|
+
baseUrl: string; // Voxket API base URL
|
|
776
|
+
|
|
777
|
+
// Optional
|
|
778
|
+
agentId?: string; // Default agent ID
|
|
779
|
+
participantName?: string; // Default participant name
|
|
780
|
+
modalities?: SessionModality[]; // Default modalities
|
|
781
|
+
debug?: boolean; // Enable debug logging
|
|
782
|
+
|
|
783
|
+
// Event Callbacks
|
|
784
|
+
onConnected?: () => void;
|
|
785
|
+
onDisconnected?: (reason?: string) => void;
|
|
786
|
+
onError?: (error: Error) => void;
|
|
787
|
+
onMessageReceived?: (message: ChatMessage) => void;
|
|
788
|
+
onTranscriptionReceived?: (transcription: TranscriptionSegment) => void;
|
|
789
|
+
onSessionStateChanged?: (state: SessionState) => void;
|
|
790
|
+
}
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
### ๐ **Connection Methods**
|
|
794
|
+
|
|
795
|
+
```typescript
|
|
796
|
+
// Connect to Voxket services
|
|
797
|
+
await client.connect(agentId?, participantName?, modalities?);
|
|
798
|
+
|
|
799
|
+
// Disconnect and cleanup
|
|
800
|
+
await client.disconnect();
|
|
801
|
+
|
|
802
|
+
// Check connection status
|
|
803
|
+
const isConnected = client.connected;
|
|
804
|
+
const state = client.getConnectionState();
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
### ๐ฌ **Session Management**
|
|
808
|
+
|
|
809
|
+
```typescript
|
|
810
|
+
// Start a new session
|
|
811
|
+
const session = await client.startSession(agentId, {
|
|
812
|
+
participantName: "User",
|
|
813
|
+
modalities: ['voice', 'chat'],
|
|
814
|
+
metadata: { customData: "value" }
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
// Get current session
|
|
818
|
+
const current = client.getCurrentSession();
|
|
819
|
+
|
|
820
|
+
// End current session
|
|
821
|
+
await client.endSession();
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
### ๐จ **UI Rendering**
|
|
825
|
+
|
|
826
|
+
```typescript
|
|
827
|
+
// Render UI widget
|
|
828
|
+
client.renderUI({
|
|
829
|
+
target: '#container', // CSS selector or HTMLElement
|
|
830
|
+
modality: ['voice', 'chat'], // Supported modalities
|
|
831
|
+
theme: 'dark', // Theme selection
|
|
832
|
+
component: 'widget', // Component type
|
|
833
|
+
displayType: 'popup', // Display mode
|
|
834
|
+
autoStart: true, // Auto-start session
|
|
835
|
+
width: '400px', // Custom width
|
|
836
|
+
height: '600px', // Custom height
|
|
837
|
+
onDisplayTypeChange: (type) => console.log(type)
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
// Remove UI
|
|
841
|
+
client.removeUI('#container');
|
|
842
|
+
client.removeAllUI();
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
### ๐ฌ **Messaging**
|
|
846
|
+
|
|
847
|
+
```typescript
|
|
848
|
+
// Send text message
|
|
849
|
+
await client.sendMessage("Hello agent!");
|
|
850
|
+
|
|
851
|
+
// Send with metadata
|
|
852
|
+
await client.sendChatMessage("Hello", { priority: "high" });
|
|
853
|
+
|
|
854
|
+
// Send file attachments (images only)
|
|
855
|
+
await client.sendAttachment(imageFile);
|
|
856
|
+
await client.sendAttachments([file1, file2]);
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
### ๐ต **Media Control Methods**
|
|
860
|
+
|
|
861
|
+
```typescript
|
|
862
|
+
// Microphone control
|
|
863
|
+
await client.toggleMicrophone();
|
|
864
|
+
await client.setMicrophoneEnabled(true);
|
|
865
|
+
const isMuted = !client.isMicrophoneEnabled;
|
|
866
|
+
|
|
867
|
+
// Camera control
|
|
868
|
+
await client.enableCamera();
|
|
869
|
+
await client.disableCamera();
|
|
870
|
+
await client.toggleCamera();
|
|
871
|
+
const isCameraOn = client.isCameraEnabled;
|
|
872
|
+
|
|
873
|
+
// Screen sharing
|
|
874
|
+
await client.startScreenShare();
|
|
875
|
+
await client.stopScreenShare();
|
|
876
|
+
const isSharing = client.isScreenShareEnabled;
|
|
877
|
+
|
|
878
|
+
// Device management
|
|
879
|
+
const audioDevices = await client.getAudioInputDevices();
|
|
880
|
+
const videoDevices = await client.getVideoInputDevices();
|
|
881
|
+
await client.setAudioInputDevice(deviceId);
|
|
882
|
+
await client.setVideoInputDevice(deviceId);
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
### ๏ฟฝ **Event System Methods**
|
|
886
|
+
|
|
887
|
+
```typescript
|
|
888
|
+
// Register custom event emitter
|
|
889
|
+
client.registerEventEmitter(
|
|
890
|
+
topic: string,
|
|
891
|
+
handler: (data: string) => void
|
|
892
|
+
): void
|
|
893
|
+
|
|
894
|
+
// Register event listener with cleanup
|
|
895
|
+
client.registerEventListener<K extends keyof VoxketEvents>(
|
|
896
|
+
eventName: K,
|
|
897
|
+
callback: (data: any) => void
|
|
898
|
+
): () => void
|
|
899
|
+
|
|
900
|
+
// Example usage
|
|
901
|
+
const unsubscribe = client.registerEventListener('chat.message.received', (msg) => {
|
|
902
|
+
console.log('Message:', msg);
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
// Cleanup
|
|
906
|
+
unsubscribe();
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
### ๏ฟฝ๐ฅ **Participant Management**
|
|
910
|
+
|
|
911
|
+
```typescript
|
|
912
|
+
// Get participants
|
|
913
|
+
const localParticipant = client.getLocalParticipant();
|
|
914
|
+
const remoteParticipants = client.getRemoteParticipants();
|
|
915
|
+
const allParticipants = client.getParticipants();
|
|
142
916
|
|
|
917
|
+
// Check permissions
|
|
918
|
+
const permissions = client.getPublishPermissions();
|
|
919
|
+
const canPublish = client.canPublishSource('microphone');
|
|
920
|
+
|
|
921
|
+
// Get media tracks
|
|
922
|
+
const micTrack = client.getMicrophoneTrack();
|
|
923
|
+
const cameraTrack = client.getCameraTrack();
|
|
924
|
+
const screenTrack = client.getScreenShareTrack();
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
## ๐ช **Interactive Components Deep Dive**
|
|
928
|
+
|
|
929
|
+
### ๐ **Creating Custom Interactive Components**
|
|
930
|
+
|
|
931
|
+
```typescript
|
|
932
|
+
import React, { useState } from 'react';
|
|
933
|
+
import { VoxketInteractiveViewProps } from '@voxket-ai/voxket-live';
|
|
934
|
+
|
|
935
|
+
function SurveyForm({ handler, data }: VoxketInteractiveViewProps) {
|
|
936
|
+
const [rating, setRating] = useState(0);
|
|
937
|
+
const [feedback, setFeedback] = useState('');
|
|
938
|
+
|
|
939
|
+
const handleSubmit = () => {
|
|
940
|
+
handler?.didSuccess({
|
|
941
|
+
survey_rating: rating,
|
|
942
|
+
customer_feedback: feedback,
|
|
943
|
+
submitted_at: new Date().toISOString()
|
|
944
|
+
});
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
const handleSkip = () => {
|
|
948
|
+
handler?.dismissView(); // Sends decline response to agent
|
|
949
|
+
};
|
|
950
|
+
|
|
951
|
+
return (
|
|
952
|
+
<div className="p-6 bg-white rounded-lg shadow-lg">
|
|
953
|
+
<h3 className="text-lg font-semibold mb-4">
|
|
954
|
+
{data?.title || 'Rate Your Experience'}
|
|
955
|
+
</h3>
|
|
956
|
+
|
|
957
|
+
<div className="mb-4">
|
|
958
|
+
<label className="block text-sm font-medium mb-2">
|
|
959
|
+
How would you rate our service?
|
|
960
|
+
</label>
|
|
961
|
+
<div className="flex gap-2">
|
|
962
|
+
{[1,2,3,4,5].map(num => (
|
|
963
|
+
<button
|
|
964
|
+
key={num}
|
|
965
|
+
onClick={() => setRating(num)}
|
|
966
|
+
className={`w-10 h-10 rounded ${
|
|
967
|
+
rating >= num ? 'bg-blue-500 text-white' : 'bg-gray-200'
|
|
968
|
+
}`}
|
|
969
|
+
>
|
|
970
|
+
{num}
|
|
971
|
+
</button>
|
|
972
|
+
))}
|
|
973
|
+
</div>
|
|
974
|
+
</div>
|
|
975
|
+
|
|
976
|
+
<div className="mb-4">
|
|
977
|
+
<label className="block text-sm font-medium mb-2">
|
|
978
|
+
Additional feedback (optional):
|
|
979
|
+
</label>
|
|
980
|
+
<textarea
|
|
981
|
+
value={feedback}
|
|
982
|
+
onChange={(e) => setFeedback(e.target.value)}
|
|
983
|
+
className="w-full p-2 border rounded"
|
|
984
|
+
rows={3}
|
|
985
|
+
/>
|
|
986
|
+
</div>
|
|
987
|
+
|
|
988
|
+
<div className="flex gap-2 justify-end">
|
|
989
|
+
<button
|
|
990
|
+
onClick={handleSkip}
|
|
991
|
+
className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded"
|
|
992
|
+
>
|
|
993
|
+
Skip
|
|
994
|
+
</button>
|
|
995
|
+
<button
|
|
996
|
+
onClick={handleSubmit}
|
|
997
|
+
disabled={rating === 0}
|
|
998
|
+
className="px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
|
|
999
|
+
>
|
|
1000
|
+
Submit
|
|
1001
|
+
</button>
|
|
1002
|
+
</div>
|
|
1003
|
+
</div>
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// Register the component
|
|
1008
|
+
await client.registerFrontendRPC(
|
|
1009
|
+
'customer_satisfaction_survey',
|
|
1010
|
+
SurveyForm,
|
|
1011
|
+
'modal' // Can be 'embedded', 'modal', or 'fullscreen'
|
|
1012
|
+
);
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
### ๐ **E-commerce Product Showcase**
|
|
1016
|
+
|
|
1017
|
+
```typescript
|
|
1018
|
+
function ProductCatalog({ handler, data }: VoxketInteractiveViewProps) {
|
|
1019
|
+
const [selectedProduct, setSelectedProduct] = useState(null);
|
|
1020
|
+
|
|
1021
|
+
const products = data?.products || [];
|
|
1022
|
+
|
|
1023
|
+
const handleSelectProduct = (product: any) => {
|
|
1024
|
+
handler?.didSuccess({
|
|
1025
|
+
selected_product: product,
|
|
1026
|
+
action: 'add_to_cart'
|
|
1027
|
+
});
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
return (
|
|
1031
|
+
<div className="p-4">
|
|
1032
|
+
<h3 className="text-xl font-bold mb-4">Recommended Products</h3>
|
|
1033
|
+
<div className="grid grid-cols-2 gap-4">
|
|
1034
|
+
{products.map((product: any) => (
|
|
1035
|
+
<div key={product.id} className="border rounded-lg p-4">
|
|
1036
|
+
<img
|
|
1037
|
+
src={product.image}
|
|
1038
|
+
alt={product.name}
|
|
1039
|
+
className="w-full h-32 object-cover rounded mb-2"
|
|
1040
|
+
/>
|
|
1041
|
+
<h4 className="font-semibold">{product.name}</h4>
|
|
1042
|
+
<p className="text-gray-600">${product.price}</p>
|
|
1043
|
+
<button
|
|
1044
|
+
onClick={() => handleSelectProduct(product)}
|
|
1045
|
+
className="mt-2 w-full bg-blue-500 text-white py-2 rounded"
|
|
1046
|
+
>
|
|
1047
|
+
Add to Cart
|
|
1048
|
+
</button>
|
|
1049
|
+
</div>
|
|
1050
|
+
))}
|
|
1051
|
+
</div>
|
|
1052
|
+
</div>
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1055
|
+
```
|
|
1056
|
+
|
|
1057
|
+
### ๐
**Appointment Scheduler**
|
|
1058
|
+
|
|
1059
|
+
```typescript
|
|
1060
|
+
function AppointmentBooker({ handler, data }: VoxketInteractiveViewProps) {
|
|
1061
|
+
const [selectedSlot, setSelectedSlot] = useState('');
|
|
1062
|
+
const [contactInfo, setContactInfo] = useState({ name: '', email: '' });
|
|
1063
|
+
|
|
1064
|
+
const availableSlots = data?.available_slots || [];
|
|
1065
|
+
|
|
1066
|
+
const handleBooking = () => {
|
|
1067
|
+
handler?.didSuccess({
|
|
1068
|
+
appointment: {
|
|
1069
|
+
slot: selectedSlot,
|
|
1070
|
+
contact: contactInfo,
|
|
1071
|
+
type: data?.appointment_type,
|
|
1072
|
+
booked_at: new Date().toISOString()
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
1075
|
+
};
|
|
1076
|
+
|
|
1077
|
+
return (
|
|
1078
|
+
<div className="p-6 bg-white rounded-lg">
|
|
1079
|
+
<h3 className="text-lg font-semibold mb-4">Book Appointment</h3>
|
|
1080
|
+
|
|
1081
|
+
<div className="mb-4">
|
|
1082
|
+
<label className="block text-sm font-medium mb-2">
|
|
1083
|
+
Available Time Slots:
|
|
1084
|
+
</label>
|
|
1085
|
+
<div className="grid grid-cols-2 gap-2">
|
|
1086
|
+
{availableSlots.map((slot: string) => (
|
|
1087
|
+
<button
|
|
1088
|
+
key={slot}
|
|
1089
|
+
onClick={() => setSelectedSlot(slot)}
|
|
1090
|
+
className={`p-2 rounded border ${
|
|
1091
|
+
selectedSlot === slot
|
|
1092
|
+
? 'bg-blue-500 text-white'
|
|
1093
|
+
: 'bg-gray-50 hover:bg-gray-100'
|
|
1094
|
+
}`}
|
|
1095
|
+
>
|
|
1096
|
+
{slot}
|
|
1097
|
+
</button>
|
|
1098
|
+
))}
|
|
1099
|
+
</div>
|
|
1100
|
+
</div>
|
|
1101
|
+
|
|
1102
|
+
<div className="mb-4">
|
|
1103
|
+
<input
|
|
1104
|
+
type="text"
|
|
1105
|
+
placeholder="Your Name"
|
|
1106
|
+
value={contactInfo.name}
|
|
1107
|
+
onChange={(e) => setContactInfo({...contactInfo, name: e.target.value})}
|
|
1108
|
+
className="w-full p-2 border rounded mb-2"
|
|
1109
|
+
/>
|
|
1110
|
+
<input
|
|
1111
|
+
type="email"
|
|
1112
|
+
placeholder="Email Address"
|
|
1113
|
+
value={contactInfo.email}
|
|
1114
|
+
onChange={(e) => setContactInfo({...contactInfo, email: e.target.value})}
|
|
1115
|
+
className="w-full p-2 border rounded"
|
|
1116
|
+
/>
|
|
1117
|
+
</div>
|
|
1118
|
+
|
|
1119
|
+
<button
|
|
1120
|
+
onClick={handleBooking}
|
|
1121
|
+
disabled={!selectedSlot || !contactInfo.name || !contactInfo.email}
|
|
1122
|
+
className="w-full bg-green-500 text-white py-2 rounded disabled:opacity-50"
|
|
1123
|
+
>
|
|
1124
|
+
Book Appointment
|
|
1125
|
+
</button>
|
|
1126
|
+
</div>
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
```
|
|
1130
|
+
|
|
1131
|
+
## ๐ **Session Analytics & Metrics**
|
|
1132
|
+
|
|
1133
|
+
### ๐ **Session Metrics Interface**
|
|
1134
|
+
|
|
1135
|
+
```typescript
|
|
1136
|
+
interface SessionMetrics {
|
|
1137
|
+
sessionId: string;
|
|
1138
|
+
startTime: Date;
|
|
1139
|
+
endTime?: Date;
|
|
1140
|
+
duration?: number; // Duration in milliseconds
|
|
1141
|
+
totalMessages: number; // Total messages exchanged
|
|
1142
|
+
connectionIssues: number; // Network issues count
|
|
1143
|
+
participantCount: number; // Number of participants
|
|
1144
|
+
events: SessionLog[]; // All session events
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
interface SessionLog {
|
|
1148
|
+
timestamp: Date;
|
|
1149
|
+
event: string; // Event type
|
|
1150
|
+
data?: any; // Event data
|
|
1151
|
+
sessionId?: string; // Associated session
|
|
1152
|
+
participantId?: string; // Participant who triggered event
|
|
1153
|
+
}
|
|
1154
|
+
```
|
|
1155
|
+
|
|
1156
|
+
### ๐ **Analytics Integration Examples**
|
|
1157
|
+
|
|
1158
|
+
```typescript
|
|
1159
|
+
// Google Analytics 4
|
|
1160
|
+
client.on('session.created', (session) => {
|
|
1161
|
+
gtag('event', 'voxket_session_start', {
|
|
1162
|
+
session_id: session.id,
|
|
1163
|
+
agent_id: session.agentId,
|
|
1164
|
+
modalities: session.activeModalities.join(',')
|
|
1165
|
+
});
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
// Mixpanel
|
|
1169
|
+
client.on('chat.message.received', (message) => {
|
|
1170
|
+
mixpanel.track('Voxket Message Received', {
|
|
1171
|
+
session_id: client.getCurrentSession()?.id,
|
|
1172
|
+
message_type: message.sender.type,
|
|
1173
|
+
message_length: message.content.length,
|
|
1174
|
+
timestamp: message.timestamp
|
|
1175
|
+
});
|
|
1176
|
+
});
|
|
1177
|
+
|
|
1178
|
+
// Custom Analytics
|
|
1179
|
+
const analyticsTracker = {
|
|
1180
|
+
trackSession: (event: string, data: any) => {
|
|
1181
|
+
fetch('/api/analytics', {
|
|
1182
|
+
method: 'POST',
|
|
1183
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1184
|
+
body: JSON.stringify({ event, data, timestamp: new Date() })
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
client.on('session.ended', (session, metrics) => {
|
|
1190
|
+
analyticsTracker.trackSession('session_completed', {
|
|
1191
|
+
duration: metrics.duration,
|
|
1192
|
+
message_count: metrics.totalMessages,
|
|
1193
|
+
quality_score: calculateQualityScore(metrics)
|
|
1194
|
+
});
|
|
1195
|
+
});
|
|
1196
|
+
```
|
|
1197
|
+
|
|
1198
|
+
## ๐ ๏ธ **Enterprise Features**
|
|
1199
|
+
|
|
1200
|
+
### ๐ **Security & Compliance**
|
|
1201
|
+
|
|
1202
|
+
```typescript
|
|
1203
|
+
// HIPAA-compliant configuration
|
|
1204
|
+
const healthcareClient = new VoxketClient({
|
|
1205
|
+
appId: "healthcare-app",
|
|
1206
|
+
appSecret: "hipaa-compliant-secret",
|
|
1207
|
+
baseUrl: "https://secure-api.voxket.com",
|
|
1208
|
+
agentId: "patient-support",
|
|
1209
|
+
|
|
1210
|
+
// Disable session logging for compliance
|
|
1211
|
+
enableSessionLogging: false,
|
|
1212
|
+
|
|
1213
|
+
onSessionStart: (sessionId) => {
|
|
1214
|
+
// HIPAA audit logging
|
|
1215
|
+
complianceLogger.logPatientInteraction({
|
|
1216
|
+
sessionId,
|
|
1217
|
+
patientId: getCurrentPatient().id,
|
|
1218
|
+
timestamp: new Date(),
|
|
1219
|
+
actionType: 'SESSION_START'
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
// Only use secure text-based modalities
|
|
1225
|
+
await healthcareClient.connect();
|
|
1226
|
+
healthcareClient.renderUI({
|
|
1227
|
+
modality: ['chat'], // Text only for security
|
|
1228
|
+
theme: 'light',
|
|
1229
|
+
enableSessionLogging: false
|
|
1230
|
+
});
|
|
1231
|
+
```
|
|
1232
|
+
|
|
1233
|
+
### ๐ข **Multi-tenant Architecture**
|
|
1234
|
+
|
|
1235
|
+
```typescript
|
|
1236
|
+
class TenantManager {
|
|
1237
|
+
private clients: Map<string, VoxketClient> = new Map();
|
|
1238
|
+
|
|
1239
|
+
async createTenantClient(tenantId: string, config: any) {
|
|
1240
|
+
const client = new VoxketClient({
|
|
1241
|
+
appId: config.appId,
|
|
1242
|
+
appSecret: config.appSecret,
|
|
1243
|
+
baseUrl: config.baseUrl,
|
|
1244
|
+
agentId: `${tenantId}-agent`,
|
|
1245
|
+
|
|
1246
|
+
onMessageReceived: (message) => {
|
|
1247
|
+
// Tenant-specific message handling
|
|
1248
|
+
this.handleTenantMessage(tenantId, message);
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
|
|
1252
|
+
this.clients.set(tenantId, client);
|
|
1253
|
+
return client;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
getTenantClient(tenantId: string) {
|
|
1257
|
+
return this.clients.get(tenantId);
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
private handleTenantMessage(tenantId: string, message: any) {
|
|
1261
|
+
// Tenant-specific analytics, logging, etc.
|
|
1262
|
+
console.log(`Tenant ${tenantId} received message:`, message);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// Usage
|
|
1267
|
+
const tenantManager = new TenantManager();
|
|
1268
|
+
const client = await tenantManager.createTenantClient('acme-corp', {
|
|
1269
|
+
appId: 'acme-app-id',
|
|
1270
|
+
appSecret: 'acme-secret',
|
|
1271
|
+
baseUrl: 'https://acme.voxket.com'
|
|
1272
|
+
});
|
|
1273
|
+
```
|
|
1274
|
+
|
|
1275
|
+
### ๐ **Advanced Session Management**
|
|
1276
|
+
|
|
1277
|
+
```typescript
|
|
1278
|
+
// Session persistence across page reloads
|
|
1279
|
+
class SessionManager {
|
|
1280
|
+
private static SESSION_KEY = 'voxket_session';
|
|
1281
|
+
|
|
1282
|
+
static saveSession(session: VoxketSession) {
|
|
1283
|
+
localStorage.setItem(this.SESSION_KEY, JSON.stringify({
|
|
1284
|
+
id: session.id,
|
|
1285
|
+
agentId: session.agentId,
|
|
1286
|
+
startedAt: session.startedAt,
|
|
1287
|
+
metadata: session.metadata
|
|
1288
|
+
}));
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
static restoreSession(): VoxketSession | null {
|
|
1292
|
+
const saved = localStorage.getItem(this.SESSION_KEY);
|
|
1293
|
+
if (saved) {
|
|
1294
|
+
try {
|
|
1295
|
+
return JSON.parse(saved);
|
|
1296
|
+
} catch {
|
|
1297
|
+
return null;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
return null;
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
static clearSession() {
|
|
1304
|
+
localStorage.removeItem(this.SESSION_KEY);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
// Restore previous session on page load
|
|
1309
|
+
const client = new VoxketClient(config);
|
|
1310
|
+
const previousSession = SessionManager.restoreSession();
|
|
1311
|
+
|
|
1312
|
+
if (previousSession) {
|
|
1313
|
+
// Attempt to reconnect to existing session
|
|
1314
|
+
try {
|
|
1315
|
+
await client.connect();
|
|
1316
|
+
// Check if session is still valid and restore UI state
|
|
1317
|
+
} catch (error) {
|
|
1318
|
+
SessionManager.clearSession();
|
|
1319
|
+
// Start fresh session
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
```
|
|
1323
|
+
|
|
1324
|
+
## ๐ง **Troubleshooting**
|
|
1325
|
+
|
|
1326
|
+
### โ **Common Issues**
|
|
1327
|
+
|
|
1328
|
+
#### **1. Widget Not Displaying**
|
|
1329
|
+
```typescript
|
|
1330
|
+
// Check console for errors and verify configuration
|
|
1331
|
+
const client = new VoxketClient({
|
|
1332
|
+
appId: "your-app-id", // โ
Make sure this is correct
|
|
1333
|
+
appSecret: "your-app-secret", // โ
Make sure this is correct
|
|
1334
|
+
baseUrl: "https://api.voxket.com", // โ
Check URL is correct
|
|
1335
|
+
debug: true // โ
Enable debug logging
|
|
1336
|
+
});
|
|
1337
|
+
```
|
|
1338
|
+
|
|
1339
|
+
#### **2. Connection Failures**
|
|
1340
|
+
```typescript
|
|
1341
|
+
client.on('connection.error', (error) => {
|
|
1342
|
+
console.error('Connection failed:', error);
|
|
1343
|
+
|
|
1344
|
+
// Common fixes:
|
|
1345
|
+
// - Verify appId and appSecret are correct
|
|
1346
|
+
// - Check baseUrl is accessible
|
|
1347
|
+
// - Ensure network connectivity
|
|
1348
|
+
// - Check for CORS issues in browser console
|
|
1349
|
+
});
|
|
1350
|
+
|
|
1351
|
+
client.on('connection.disconnected', (reason) => {
|
|
1352
|
+
console.log('Disconnected reason:', reason);
|
|
1353
|
+
|
|
1354
|
+
// Auto-reconnect logic
|
|
1355
|
+
setTimeout(() => {
|
|
1356
|
+
client.connect().catch(console.error);
|
|
1357
|
+
}, 5000);
|
|
1358
|
+
});
|
|
1359
|
+
```
|
|
1360
|
+
|
|
1361
|
+
#### **3. Microphone/Camera Permission Issues**
|
|
1362
|
+
```typescript
|
|
1363
|
+
// Handle permission errors gracefully
|
|
1364
|
+
client.on('connection.error', (error) => {
|
|
1365
|
+
if (error.code === 'PERMISSION_DENIED') {
|
|
1366
|
+
showUserMessage('Please allow microphone/camera access to continue');
|
|
1367
|
+
}
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1370
|
+
// Request permissions explicitly
|
|
1371
|
+
navigator.mediaDevices.getUserMedia({
|
|
1372
|
+
audio: true,
|
|
1373
|
+
video: true
|
|
1374
|
+
}).then(() => {
|
|
1375
|
+
console.log('Permissions granted');
|
|
1376
|
+
}).catch((error) => {
|
|
1377
|
+
console.error('Permission denied:', error);
|
|
1378
|
+
});
|
|
1379
|
+
```
|
|
1380
|
+
|
|
1381
|
+
#### **4. React Strict Mode Issues**
|
|
1382
|
+
```typescript
|
|
1383
|
+
// For React 18 Strict Mode, wrap your app properly
|
|
143
1384
|
function App() {
|
|
144
|
-
const [
|
|
145
|
-
|
|
1385
|
+
const [client, setClient] = useState<VoxketClient | null>(null);
|
|
1386
|
+
|
|
1387
|
+
useEffect(() => {
|
|
1388
|
+
// Only create client once
|
|
1389
|
+
if (!client) {
|
|
1390
|
+
const newClient = new VoxketClient(config);
|
|
1391
|
+
setClient(newClient);
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
return () => {
|
|
1395
|
+
// Cleanup on unmount
|
|
1396
|
+
client?.disconnect();
|
|
1397
|
+
};
|
|
1398
|
+
}, []);
|
|
1399
|
+
|
|
1400
|
+
if (!client) return <div>Loading...</div>;
|
|
1401
|
+
|
|
1402
|
+
return <VoxketWidget voxketClient={client} {...props} />;
|
|
1403
|
+
}
|
|
1404
|
+
```
|
|
146
1405
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
1406
|
+
### ๐ **Debug Mode**
|
|
1407
|
+
|
|
1408
|
+
```typescript
|
|
1409
|
+
// Enable comprehensive debugging
|
|
1410
|
+
const client = new VoxketClient({
|
|
1411
|
+
// ... config
|
|
1412
|
+
debug: true
|
|
1413
|
+
});
|
|
1414
|
+
|
|
1415
|
+
// Monitor all events
|
|
1416
|
+
client.onAny((eventName, ...args) => {
|
|
1417
|
+
console.log(`๐ Event: ${eventName}`, args);
|
|
1418
|
+
});
|
|
1419
|
+
|
|
1420
|
+
// Check connection state
|
|
1421
|
+
console.log('Connection state:', client.getConnectionState());
|
|
1422
|
+
console.log('Current session:', client.getCurrentSession());
|
|
1423
|
+
console.log('Is connected:', client.connected);
|
|
1424
|
+
```
|
|
1425
|
+
|
|
1426
|
+
### ๐ ๏ธ **Performance Optimization**
|
|
1427
|
+
|
|
1428
|
+
```typescript
|
|
1429
|
+
// Optimize for production
|
|
1430
|
+
const client = new VoxketClient({
|
|
1431
|
+
// ... config
|
|
1432
|
+
debug: false, // Disable debug logs
|
|
1433
|
+
});
|
|
1434
|
+
|
|
1435
|
+
// Lazy load the widget
|
|
1436
|
+
const LazyVoxketWidget = lazy(() => import('@voxket-ai/voxket-live'));
|
|
1437
|
+
|
|
1438
|
+
function App() {
|
|
1439
|
+
return (
|
|
1440
|
+
<Suspense fallback={<div>Loading chat...</div>}>
|
|
1441
|
+
<LazyVoxketWidget {...props} />
|
|
1442
|
+
</Suspense>
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
// Preload on user interaction
|
|
1447
|
+
const preloadChat = () => {
|
|
1448
|
+
import('@voxket-ai/voxket-live').then(() => {
|
|
1449
|
+
console.log('Voxket SDK preloaded');
|
|
1450
|
+
});
|
|
1451
|
+
};
|
|
1452
|
+
|
|
1453
|
+
// Call preloadChat() on hover or focus events
|
|
1454
|
+
```
|
|
1455
|
+
|
|
1456
|
+
## ๐ฏ **Best Practices**
|
|
1457
|
+
|
|
1458
|
+
### ๐๏ธ **Application Architecture**
|
|
1459
|
+
|
|
1460
|
+
#### **1. Client Instance Management**
|
|
1461
|
+
```typescript
|
|
1462
|
+
// โ
Good: Single client instance
|
|
1463
|
+
class VoxketManager {
|
|
1464
|
+
private static instance: VoxketClient | null = null;
|
|
1465
|
+
|
|
1466
|
+
static getInstance(config: VoxketClientConfig): VoxketClient {
|
|
1467
|
+
if (!this.instance) {
|
|
1468
|
+
this.instance = new VoxketClient(config);
|
|
1469
|
+
}
|
|
1470
|
+
return this.instance;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
static cleanup() {
|
|
1474
|
+
if (this.instance) {
|
|
1475
|
+
this.instance.disconnect();
|
|
1476
|
+
this.instance = null;
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
// โ Bad: Multiple client instances
|
|
1482
|
+
function BadComponent() {
|
|
1483
|
+
const [client] = useState(() => new VoxketClient(config)); // Creates new client each render
|
|
1484
|
+
}
|
|
1485
|
+
```
|
|
1486
|
+
|
|
1487
|
+
#### **2. Error Handling**
|
|
1488
|
+
```typescript
|
|
1489
|
+
// โ
Comprehensive error handling
|
|
1490
|
+
async function initializeVoxket() {
|
|
1491
|
+
try {
|
|
1492
|
+
await client.connect();
|
|
1493
|
+
client.renderUI({ target: '#voxket-widget' });
|
|
1494
|
+
} catch (error) {
|
|
1495
|
+
if (error.code === 'AUTHENTICATION_FAILED') {
|
|
1496
|
+
showError('Invalid credentials');
|
|
1497
|
+
} else if (error.code === 'NETWORK_ERROR') {
|
|
1498
|
+
showError('Connection failed - please try again');
|
|
1499
|
+
} else {
|
|
1500
|
+
showError('Something went wrong');
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
// Log for debugging
|
|
1504
|
+
console.error('Voxket initialization failed:', error);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
```
|
|
1508
|
+
|
|
1509
|
+
#### **3. Event Cleanup**
|
|
1510
|
+
```typescript
|
|
1511
|
+
// โ
Always cleanup event listeners
|
|
1512
|
+
useEffect(() => {
|
|
1513
|
+
const handleMessage = (message: ChatMessage) => {
|
|
1514
|
+
// Handle message
|
|
151
1515
|
};
|
|
1516
|
+
|
|
1517
|
+
client.on('chat.message.received', handleMessage);
|
|
1518
|
+
|
|
1519
|
+
return () => {
|
|
1520
|
+
client.off('chat.message.received', handleMessage);
|
|
1521
|
+
};
|
|
1522
|
+
}, [client]);
|
|
1523
|
+
```
|
|
1524
|
+
|
|
1525
|
+
### ๐ฑ **User Experience**
|
|
1526
|
+
|
|
1527
|
+
#### **1. Loading States**
|
|
1528
|
+
```typescript
|
|
1529
|
+
function ChatWidget() {
|
|
1530
|
+
const [isConnecting, setIsConnecting] = useState(false);
|
|
1531
|
+
const [connectionError, setConnectionError] = useState('');
|
|
1532
|
+
|
|
1533
|
+
const initChat = async () => {
|
|
1534
|
+
setIsConnecting(true);
|
|
1535
|
+
setConnectionError('');
|
|
1536
|
+
|
|
1537
|
+
try {
|
|
1538
|
+
await client.connect();
|
|
1539
|
+
client.renderUI({ target: '#chat' });
|
|
1540
|
+
} catch (error) {
|
|
1541
|
+
setConnectionError('Failed to connect. Please try again.');
|
|
1542
|
+
} finally {
|
|
1543
|
+
setIsConnecting(false);
|
|
1544
|
+
}
|
|
1545
|
+
};
|
|
1546
|
+
|
|
1547
|
+
return (
|
|
1548
|
+
<div>
|
|
1549
|
+
{isConnecting && <div>Connecting to support...</div>}
|
|
1550
|
+
{connectionError && <div className="error">{connectionError}</div>}
|
|
1551
|
+
<button onClick={initChat} disabled={isConnecting}>
|
|
1552
|
+
Start Chat
|
|
1553
|
+
</button>
|
|
1554
|
+
<div id="chat"></div>
|
|
1555
|
+
</div>
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1558
|
+
```
|
|
152
1559
|
|
|
153
|
-
|
|
1560
|
+
#### **2. Progressive Enhancement**
|
|
1561
|
+
```typescript
|
|
1562
|
+
// Start with basic features, enhance based on capabilities
|
|
1563
|
+
const client = new VoxketClient(config);
|
|
1564
|
+
|
|
1565
|
+
// Check agent capabilities
|
|
1566
|
+
const agentInfo = client.getCurrentAgentInfo();
|
|
1567
|
+
const supportedModalities = agentInfo?.modality_supported || ['chat'];
|
|
1568
|
+
|
|
1569
|
+
// Render appropriate UI
|
|
1570
|
+
client.renderUI({
|
|
1571
|
+
modality: supportedModalities.includes('voice')
|
|
1572
|
+
? ['voice', 'chat']
|
|
1573
|
+
: ['chat'],
|
|
1574
|
+
theme: userPreferences.theme || 'vox'
|
|
1575
|
+
});
|
|
1576
|
+
```
|
|
1577
|
+
|
|
1578
|
+
#### **3. Accessibility**
|
|
1579
|
+
```typescript
|
|
1580
|
+
// Ensure keyboard navigation and screen reader support
|
|
1581
|
+
<VoxketWidget
|
|
1582
|
+
className="voxket-accessible"
|
|
1583
|
+
// Widget automatically includes ARIA labels and keyboard support
|
|
1584
|
+
{...props}
|
|
1585
|
+
/>
|
|
1586
|
+
|
|
1587
|
+
/* CSS for better accessibility */
|
|
1588
|
+
.voxket-accessible {
|
|
1589
|
+
/* Ensure focus indicators are visible */
|
|
1590
|
+
--focus-ring-color: #3b82f6;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
.voxket-accessible *:focus {
|
|
1594
|
+
outline: 2px solid var(--focus-ring-color);
|
|
1595
|
+
outline-offset: 2px;
|
|
1596
|
+
}
|
|
1597
|
+
```
|
|
1598
|
+
|
|
1599
|
+
### ๐ **Security**
|
|
1600
|
+
|
|
1601
|
+
#### **1. Credential Management**
|
|
1602
|
+
```typescript
|
|
1603
|
+
// โ
Use environment variables
|
|
1604
|
+
const client = new VoxketClient({
|
|
1605
|
+
appId: process.env.VOXKET_APP_ID,
|
|
1606
|
+
appSecret: process.env.VOXKET_APP_SECRET,
|
|
1607
|
+
baseUrl: process.env.VOXKET_BASE_URL
|
|
1608
|
+
});
|
|
1609
|
+
|
|
1610
|
+
// โ
For browser apps, use backend proxy
|
|
1611
|
+
async function getVoxketCredentials() {
|
|
1612
|
+
const response = await fetch('/api/voxket-auth', {
|
|
1613
|
+
headers: {
|
|
1614
|
+
'Authorization': `Bearer ${userToken}`
|
|
1615
|
+
}
|
|
1616
|
+
});
|
|
1617
|
+
return response.json();
|
|
1618
|
+
}
|
|
1619
|
+
```
|
|
1620
|
+
|
|
1621
|
+
#### **2. Content Security Policy**
|
|
1622
|
+
```html
|
|
1623
|
+
<!-- Add CSP headers for security -->
|
|
1624
|
+
<meta http-equiv="Content-Security-Policy"
|
|
1625
|
+
content="connect-src 'self' wss://*.voxket.com https://*.voxket.com;">
|
|
1626
|
+
```
|
|
1627
|
+
|
|
1628
|
+
## ๐ **Framework Integration Examples**
|
|
1629
|
+
|
|
1630
|
+
### โ๏ธ **React with TypeScript**
|
|
1631
|
+
```typescript
|
|
1632
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
1633
|
+
import VoxketWidget, {
|
|
1634
|
+
VoxketWidgetProps,
|
|
1635
|
+
VoxketClient,
|
|
1636
|
+
SessionMetrics
|
|
1637
|
+
} from '@voxket-ai/voxket-live';
|
|
1638
|
+
|
|
1639
|
+
interface Props {
|
|
1640
|
+
agentId: string;
|
|
1641
|
+
userId: string;
|
|
1642
|
+
userRole: 'customer' | 'admin';
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
export function CustomerSupport({ agentId, userId, userRole }: Props) {
|
|
1646
|
+
const [sessionMetrics, setSessionMetrics] = useState<SessionMetrics | null>(null);
|
|
1647
|
+
const [isActive, setIsActive] = useState(false);
|
|
1648
|
+
|
|
1649
|
+
const handleSessionStart = useCallback((sessionId: string) => {
|
|
1650
|
+
setIsActive(true);
|
|
1651
|
+
console.log('Support session started:', sessionId);
|
|
1652
|
+
}, []);
|
|
1653
|
+
|
|
1654
|
+
const handleSessionEnd = useCallback((metrics: SessionMetrics) => {
|
|
154
1655
|
setSessionMetrics(metrics);
|
|
155
|
-
|
|
156
|
-
|
|
1656
|
+
setIsActive(false);
|
|
1657
|
+
console.log('Session ended:', metrics);
|
|
1658
|
+
}, []);
|
|
1659
|
+
|
|
1660
|
+
const widgetProps: VoxketWidgetProps = {
|
|
1661
|
+
agentId,
|
|
1662
|
+
baseUrl: process.env.NEXT_PUBLIC_VOXKET_BASE_URL!,
|
|
1663
|
+
appId: process.env.NEXT_PUBLIC_VOXKET_APP_ID!,
|
|
1664
|
+
appSecret: process.env.NEXT_PUBLIC_VOXKET_APP_SECRET!,
|
|
1665
|
+
participantName: `User-${userId}`,
|
|
1666
|
+
theme: 'vox',
|
|
1667
|
+
modalities: ['chat', 'voice'],
|
|
1668
|
+
displayType: 'popup',
|
|
1669
|
+
popupPosition: 'bottom-right',
|
|
1670
|
+
onSessionStart: handleSessionStart,
|
|
1671
|
+
onSessionEnd: handleSessionEnd
|
|
157
1672
|
};
|
|
158
1673
|
|
|
159
1674
|
return (
|
|
160
|
-
<
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
1675
|
+
<div className="customer-support">
|
|
1676
|
+
{isActive && (
|
|
1677
|
+
<div className="status-indicator">
|
|
1678
|
+
๐ข Support session active
|
|
1679
|
+
</div>
|
|
1680
|
+
)}
|
|
1681
|
+
|
|
1682
|
+
<VoxketWidget {...widgetProps} />
|
|
1683
|
+
|
|
1684
|
+
{sessionMetrics && (
|
|
1685
|
+
<div className="session-summary">
|
|
1686
|
+
<h4>Session Summary</h4>
|
|
1687
|
+
<p>Duration: {Math.round(sessionMetrics.duration! / 1000)}s</p>
|
|
1688
|
+
<p>Messages: {sessionMetrics.totalMessages}</p>
|
|
1689
|
+
</div>
|
|
1690
|
+
)}
|
|
1691
|
+
</div>
|
|
167
1692
|
);
|
|
168
1693
|
}
|
|
169
1694
|
```
|
|
170
1695
|
|
|
171
|
-
###
|
|
1696
|
+
### ๐ **Vue 3 Composition API**
|
|
1697
|
+
```typescript
|
|
1698
|
+
<template>
|
|
1699
|
+
<div class="vue-voxket">
|
|
1700
|
+
<button @click="initializeChat" :disabled="isLoading">
|
|
1701
|
+
Start Support Chat
|
|
1702
|
+
</button>
|
|
1703
|
+
<div ref="voxketContainer" class="voxket-container"></div>
|
|
1704
|
+
</div>
|
|
1705
|
+
</template>
|
|
1706
|
+
|
|
1707
|
+
<script setup lang="ts">
|
|
1708
|
+
import { ref, onMounted, onUnmounted } from 'vue';
|
|
1709
|
+
import { VoxketClient } from '@voxket-ai/voxket-live';
|
|
1710
|
+
|
|
1711
|
+
const voxketContainer = ref<HTMLElement>();
|
|
1712
|
+
const isLoading = ref(false);
|
|
1713
|
+
let client: VoxketClient | null = null;
|
|
1714
|
+
|
|
1715
|
+
const initializeChat = async () => {
|
|
1716
|
+
if (!client || !voxketContainer.value) return;
|
|
1717
|
+
|
|
1718
|
+
isLoading.value = true;
|
|
1719
|
+
|
|
1720
|
+
try {
|
|
1721
|
+
await client.connect();
|
|
1722
|
+
client.renderUI({
|
|
1723
|
+
target: voxketContainer.value,
|
|
1724
|
+
modality: ['chat'],
|
|
1725
|
+
theme: 'light',
|
|
1726
|
+
autoStart: true
|
|
1727
|
+
});
|
|
1728
|
+
} catch (error) {
|
|
1729
|
+
console.error('Failed to initialize chat:', error);
|
|
1730
|
+
} finally {
|
|
1731
|
+
isLoading.value = false;
|
|
1732
|
+
}
|
|
1733
|
+
};
|
|
1734
|
+
|
|
1735
|
+
onMounted(() => {
|
|
1736
|
+
client = new VoxketClient({
|
|
1737
|
+
appId: import.meta.env.VITE_VOXKET_APP_ID,
|
|
1738
|
+
appSecret: import.meta.env.VITE_VOXKET_APP_SECRET,
|
|
1739
|
+
baseUrl: import.meta.env.VITE_VOXKET_BASE_URL,
|
|
1740
|
+
agentId: 'vue-support-agent'
|
|
1741
|
+
});
|
|
1742
|
+
});
|
|
1743
|
+
|
|
1744
|
+
onUnmounted(() => {
|
|
1745
|
+
if (client) {
|
|
1746
|
+
client.removeAllUI();
|
|
1747
|
+
client.disconnect();
|
|
1748
|
+
}
|
|
1749
|
+
});
|
|
1750
|
+
</script>
|
|
1751
|
+
```
|
|
1752
|
+
|
|
1753
|
+
### ๐
ฐ๏ธ **Angular Component**
|
|
1754
|
+
```typescript
|
|
1755
|
+
// voxket.service.ts
|
|
1756
|
+
import { Injectable } from '@angular/core';
|
|
1757
|
+
import { VoxketClient } from '@voxket-ai/voxket-live';
|
|
1758
|
+
|
|
1759
|
+
@Injectable({ providedIn: 'root' })
|
|
1760
|
+
export class VoxketService {
|
|
1761
|
+
private client: VoxketClient;
|
|
1762
|
+
|
|
1763
|
+
constructor() {
|
|
1764
|
+
this.client = new VoxketClient({
|
|
1765
|
+
appId: environment.voxketAppId,
|
|
1766
|
+
appSecret: environment.voxketAppSecret,
|
|
1767
|
+
baseUrl: environment.voxketBaseUrl
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
async startChat(containerId: string, agentId: string) {
|
|
1772
|
+
await this.client.connect();
|
|
1773
|
+
this.client.renderUI({
|
|
1774
|
+
target: `#${containerId}`,
|
|
1775
|
+
agentId,
|
|
1776
|
+
modality: ['chat'],
|
|
1777
|
+
theme: 'dark'
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
disconnect() {
|
|
1782
|
+
this.client.removeAllUI();
|
|
1783
|
+
this.client.disconnect();
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
// chat.component.ts
|
|
1788
|
+
@Component({
|
|
1789
|
+
selector: 'app-chat',
|
|
1790
|
+
template: `
|
|
1791
|
+
<div class="chat-container">
|
|
1792
|
+
<button (click)="startChat()" [disabled]="isLoading">
|
|
1793
|
+
{{ isLoading ? 'Connecting...' : 'Start Chat' }}
|
|
1794
|
+
</button>
|
|
1795
|
+
<div id="angular-voxket-container"></div>
|
|
1796
|
+
</div>
|
|
1797
|
+
`
|
|
1798
|
+
})
|
|
1799
|
+
export class ChatComponent implements OnDestroy {
|
|
1800
|
+
isLoading = false;
|
|
1801
|
+
|
|
1802
|
+
constructor(private voxketService: VoxketService) {}
|
|
1803
|
+
|
|
1804
|
+
async startChat() {
|
|
1805
|
+
this.isLoading = true;
|
|
1806
|
+
try {
|
|
1807
|
+
await this.voxketService.startChat('angular-voxket-container', 'support-agent');
|
|
1808
|
+
} finally {
|
|
1809
|
+
this.isLoading = false;
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
ngOnDestroy() {
|
|
1814
|
+
this.voxketService.disconnect();
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
```
|
|
1818
|
+
|
|
1819
|
+
### ๐ช **Svelte Integration**
|
|
1820
|
+
```svelte
|
|
1821
|
+
<!-- VoxketChat.svelte -->
|
|
1822
|
+
<script lang="ts">
|
|
1823
|
+
import { onMount, onDestroy } from 'svelte';
|
|
1824
|
+
import { VoxketClient } from '@voxket-ai/voxket-live';
|
|
1825
|
+
|
|
1826
|
+
export let agentId: string;
|
|
1827
|
+
export let theme: 'dark' | 'light' | 'vox' = 'vox';
|
|
1828
|
+
|
|
1829
|
+
let container: HTMLElement;
|
|
1830
|
+
let client: VoxketClient;
|
|
1831
|
+
let isConnected = false;
|
|
1832
|
+
|
|
1833
|
+
onMount(() => {
|
|
1834
|
+
client = new VoxketClient({
|
|
1835
|
+
appId: import.meta.env.VITE_VOXKET_APP_ID,
|
|
1836
|
+
appSecret: import.meta.env.VITE_VOXKET_APP_SECRET,
|
|
1837
|
+
baseUrl: import.meta.env.VITE_VOXKET_BASE_URL,
|
|
1838
|
+
|
|
1839
|
+
onConnected: () => {
|
|
1840
|
+
isConnected = true;
|
|
1841
|
+
},
|
|
1842
|
+
|
|
1843
|
+
onDisconnected: () => {
|
|
1844
|
+
isConnected = false;
|
|
1845
|
+
}
|
|
1846
|
+
});
|
|
1847
|
+
});
|
|
1848
|
+
|
|
1849
|
+
async function startChat() {
|
|
1850
|
+
if (!client || !container) return;
|
|
1851
|
+
|
|
1852
|
+
try {
|
|
1853
|
+
await client.connect();
|
|
1854
|
+
client.renderUI({
|
|
1855
|
+
target: container,
|
|
1856
|
+
agentId,
|
|
1857
|
+
modality: ['chat'],
|
|
1858
|
+
theme
|
|
1859
|
+
});
|
|
1860
|
+
} catch (error) {
|
|
1861
|
+
console.error('Chat initialization failed:', error);
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
onDestroy(() => {
|
|
1866
|
+
if (client) {
|
|
1867
|
+
client.removeAllUI();
|
|
1868
|
+
client.disconnect();
|
|
1869
|
+
}
|
|
1870
|
+
});
|
|
1871
|
+
</script>
|
|
1872
|
+
|
|
1873
|
+
<div class="svelte-voxket">
|
|
1874
|
+
<button on:click={startChat} disabled={!client}>
|
|
1875
|
+
{isConnected ? '๐ฌ Chat Active' : 'Start Chat'}
|
|
1876
|
+
</button>
|
|
1877
|
+
|
|
1878
|
+
<div bind:this={container} class="chat-container"></div>
|
|
1879
|
+
</div>
|
|
1880
|
+
|
|
1881
|
+
<style>
|
|
1882
|
+
.chat-container {
|
|
1883
|
+
width: 400px;
|
|
1884
|
+
height: 600px;
|
|
1885
|
+
border-radius: 12px;
|
|
1886
|
+
overflow: hidden;
|
|
1887
|
+
}
|
|
1888
|
+
</style>
|
|
1889
|
+
```
|
|
1890
|
+
|
|
1891
|
+
## ๐ **Deployment & Production**
|
|
1892
|
+
|
|
1893
|
+
### ๐ญ **Production Checklist**
|
|
1894
|
+
|
|
1895
|
+
```typescript
|
|
1896
|
+
// โ
Production configuration
|
|
1897
|
+
const client = new VoxketClient({
|
|
1898
|
+
appId: process.env.VOXKET_APP_ID!, // From secure environment
|
|
1899
|
+
appSecret: process.env.VOXKET_APP_SECRET!, // From secure environment
|
|
1900
|
+
baseUrl: process.env.VOXKET_BASE_URL!, // Production URL
|
|
1901
|
+
debug: false, // Disable debug logs
|
|
1902
|
+
|
|
1903
|
+
// Error tracking
|
|
1904
|
+
onError: (error) => {
|
|
1905
|
+
// Send to error monitoring service (Sentry, etc.)
|
|
1906
|
+
console.error('Voxket error:', error);
|
|
1907
|
+
errorTracker.captureException(error);
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
|
|
1911
|
+
// โ
Health check endpoint
|
|
1912
|
+
app.get('/health/voxket', async (req, res) => {
|
|
1913
|
+
try {
|
|
1914
|
+
// Test Voxket API connectivity
|
|
1915
|
+
const response = await fetch(`${process.env.VOXKET_BASE_URL}/health`);
|
|
1916
|
+
if (response.ok) {
|
|
1917
|
+
res.status(200).json({ status: 'healthy' });
|
|
1918
|
+
} else {
|
|
1919
|
+
res.status(503).json({ status: 'unhealthy' });
|
|
1920
|
+
}
|
|
1921
|
+
} catch (error) {
|
|
1922
|
+
res.status(503).json({ status: 'error', error: error.message });
|
|
1923
|
+
}
|
|
1924
|
+
});
|
|
1925
|
+
```
|
|
1926
|
+
|
|
1927
|
+
### ๐ **Monitoring & Analytics**
|
|
1928
|
+
|
|
1929
|
+
```typescript
|
|
1930
|
+
// Production monitoring setup
|
|
1931
|
+
class VoxketMonitoring {
|
|
1932
|
+
static setupMonitoring(client: VoxketClient) {
|
|
1933
|
+
// Connection monitoring
|
|
1934
|
+
client.on('connection.connected', () => {
|
|
1935
|
+
this.trackEvent('voxket_connected');
|
|
1936
|
+
});
|
|
1937
|
+
|
|
1938
|
+
client.on('connection.error', (error) => {
|
|
1939
|
+
this.trackError('voxket_connection_error', error);
|
|
1940
|
+
});
|
|
1941
|
+
|
|
1942
|
+
// Session analytics
|
|
1943
|
+
client.on('session.created', (session) => {
|
|
1944
|
+
this.trackEvent('voxket_session_start', {
|
|
1945
|
+
session_id: session.id,
|
|
1946
|
+
agent_id: session.agentId
|
|
1947
|
+
});
|
|
1948
|
+
});
|
|
1949
|
+
|
|
1950
|
+
// Performance monitoring
|
|
1951
|
+
const startTime = Date.now();
|
|
1952
|
+
client.on('connection.connected', () => {
|
|
1953
|
+
const connectionTime = Date.now() - startTime;
|
|
1954
|
+
this.trackTiming('voxket_connection_time', connectionTime);
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
private static trackEvent(event: string, data?: any) {
|
|
1959
|
+
// Send to your analytics service
|
|
1960
|
+
analytics.track(event, data);
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
private static trackError(event: string, error: Error) {
|
|
1964
|
+
// Send to error monitoring
|
|
1965
|
+
errorTracker.captureException(error, { tags: { component: 'voxket' } });
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
private static trackTiming(metric: string, duration: number) {
|
|
1969
|
+
// Send to performance monitoring
|
|
1970
|
+
performanceTracker.timing(metric, duration);
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
// Apply monitoring
|
|
1975
|
+
VoxketMonitoring.setupMonitoring(client);
|
|
1976
|
+
```
|
|
1977
|
+
|
|
1978
|
+
## ๐ **API Reference Summary**
|
|
1979
|
+
|
|
1980
|
+
### ๐๏ธ **Core Classes**
|
|
1981
|
+
|
|
1982
|
+
- **`VoxketClient`** - Main SDK client for programmatic control
|
|
1983
|
+
- **`VoxketWidget`** - React component for easy integration
|
|
1984
|
+
- **`VoxketProvider`** - React context provider for advanced usage
|
|
1985
|
+
|
|
1986
|
+
### ๐จ **Display Types**
|
|
1987
|
+
|
|
1988
|
+
- **`widget`** - Embedded widget mode
|
|
1989
|
+
- **`popup`** - Floating popup mode
|
|
1990
|
+
- **`fullscreen`** - Full-screen overlay mode
|
|
1991
|
+
|
|
1992
|
+
### ๐ญ **Themes**
|
|
1993
|
+
|
|
1994
|
+
- **`vox`** - Default Voxket branded theme
|
|
1995
|
+
- **`dark`** - Dark mode theme
|
|
1996
|
+
- **`light`** - Light mode theme
|
|
1997
|
+
- **Custom** - Create your own theme object
|
|
1998
|
+
|
|
1999
|
+
### ๐ช **Modalities**
|
|
2000
|
+
|
|
2001
|
+
- **`voice`** - Voice conversations with transcription
|
|
2002
|
+
- **`chat`** - Text-based messaging
|
|
2003
|
+
- **`video`** - Video calls with camera support
|
|
2004
|
+
- **`screen_share`** - Screen sharing capability
|
|
2005
|
+
|
|
2006
|
+
### ๐ก **Event Categories**
|
|
2007
|
+
|
|
2008
|
+
- **Connection Events** - `connection.*`
|
|
2009
|
+
- **Session Events** - `session.*`
|
|
2010
|
+
- **Chat Events** - `chat.*`
|
|
2011
|
+
- **Agent Events** - `agent.*`
|
|
2012
|
+
- **Media Events** - `track.*`
|
|
2013
|
+
- **RPC Events** - `rpc.*`
|
|
2014
|
+
|
|
2015
|
+
## ๐ค **Community & Support**
|
|
2016
|
+
|
|
2017
|
+
### ๐ **Documentation**
|
|
2018
|
+
- [API Reference](https://docs.voxket.com/api)
|
|
2019
|
+
- [Integration Guides](https://docs.voxket.com/guides)
|
|
2020
|
+
- [Example Projects](https://github.com/voxket-ai/examples)
|
|
2021
|
+
|
|
2022
|
+
### ๐ **Getting Help**
|
|
2023
|
+
- [GitHub Issues](https://github.com/voxket-ai/voxket-web-sdk/issues)
|
|
2024
|
+
- [Discord Community](https://discord.gg/voxket)
|
|
2025
|
+
- [Support Email](mailto:support@voxket.com)
|
|
172
2026
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
- `CONNECTION_ISSUE` - When connection problems occur
|
|
2027
|
+
### ๐งช **Contributing**
|
|
2028
|
+
1. Fork the repository
|
|
2029
|
+
2. Create a feature branch
|
|
2030
|
+
3. Make your changes
|
|
2031
|
+
4. Add tests
|
|
2032
|
+
5. Submit a pull request
|
|
180
2033
|
|
|
181
|
-
|
|
2034
|
+
### ๐ **License**
|
|
2035
|
+
MIT License - see [LICENSE](./LICENSE) file for details.
|
|
182
2036
|
|
|
183
|
-
|
|
2037
|
+
---
|
|
184
2038
|
|
|
185
|
-
|
|
186
|
-
1. **Size:** Use the `width` and `height` props.
|
|
187
|
-
2. **Custom CSS:** Add your own styles by passing a `className` to the widget and defining corresponding CSS rules in your project.
|
|
188
|
-
3. **Tailwind Overrides:** If your project also uses Tailwind CSS, you might be able to override styles by ensuring your Tailwind configuration and selectors have higher specificity if needed.
|
|
2039
|
+
## ๐ **Ready to Get Started?**
|
|
189
2040
|
|
|
190
|
-
|
|
2041
|
+
1. **Install the SDK**: `npm install @voxket-ai/voxket-live`
|
|
2042
|
+
2. **Get your credentials** from the [Voxket Dashboard](https://dashboard.voxket.com)
|
|
2043
|
+
3. **Choose your integration method** (Widget, Client SDK, or Advanced React)
|
|
2044
|
+
4. **Start building amazing AI-powered experiences!**
|
|
191
2045
|
|
|
192
|
-
|
|
2046
|
+
### ๐ก **Need help?**
|
|
2047
|
+
Check out our [Quick Start Guide](https://docs.voxket.com/quickstart) or join our [Discord community](https://discord.gg/voxket) for real-time support!
|
|
193
2048
|
|
|
194
|
-
|
|
2049
|
+
---
|
|
195
2050
|
|
|
196
|
-
|
|
2051
|
+
**Built with โค๏ธ by the Voxket team**
|