@hamsa-ai/voice-agents-sdk 0.4.0-beta.1 → 0.4.0-beta.2
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 +351 -123
- package/dist/index.cjs.js +2 -1
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.esm.js +2 -1
- package/dist/index.esm.js.map +1 -0
- package/dist/index.umd.js +2 -1
- package/dist/index.umd.js.map +1 -0
- package/package.json +22 -13
- package/types/classes/livekit-analytics.d.ts +370 -0
- package/types/classes/livekit-audio-manager.d.ts +738 -0
- package/types/classes/livekit-connection.d.ts +318 -0
- package/types/classes/livekit-manager.d.ts +527 -0
- package/types/classes/livekit-tool-registry.d.ts +607 -0
- package/types/classes/{screen_wake_lock.d.ts → screen-wake-lock.d.ts} +4 -4
- package/types/classes/types.d.ts +325 -0
- package/types/main.d.ts +679 -56
- package/types/classes/livekit_manager.d.ts +0 -118
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Then, you can initialize the agent like this:
|
|
|
40
40
|
const agent = new HamsaVoiceAgent("YOUR_API_KEY");
|
|
41
41
|
|
|
42
42
|
agent.on("callStarted", () => {
|
|
43
|
-
|
|
43
|
+
console.log("Conversation has started!");
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
// Example: Start a call
|
|
@@ -55,11 +55,19 @@ Start a conversation with an existing agent by calling the "start" function. You
|
|
|
55
55
|
|
|
56
56
|
```javascript
|
|
57
57
|
agent.start({
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
agentId: YOUR_AGENT_ID,
|
|
59
|
+
params: {
|
|
60
|
+
param1: "NAME",
|
|
61
|
+
param2: "NAME2",
|
|
62
|
+
},
|
|
63
|
+
voiceEnablement: true,
|
|
64
|
+
userId: "user-123", // Optional user tracking
|
|
65
|
+
preferHeadphonesForIosDevices: true, // iOS audio optimization
|
|
66
|
+
connectionDelay: {
|
|
67
|
+
android: 3000, // 3 second delay for Android
|
|
68
|
+
ios: 0,
|
|
69
|
+
default: 0,
|
|
70
|
+
},
|
|
63
71
|
});
|
|
64
72
|
```
|
|
65
73
|
|
|
@@ -87,6 +95,135 @@ To end a conversation, simply call the "end" function:
|
|
|
87
95
|
agent.end();
|
|
88
96
|
```
|
|
89
97
|
|
|
98
|
+
## Advanced Audio Controls
|
|
99
|
+
|
|
100
|
+
The SDK provides comprehensive audio control features for professional voice applications:
|
|
101
|
+
|
|
102
|
+
### Volume Management
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
// Set agent voice volume (0.0 to 1.0)
|
|
106
|
+
agent.setVolume(0.8);
|
|
107
|
+
|
|
108
|
+
// Get current output volume
|
|
109
|
+
const currentVolume = agent.getOutputVolume();
|
|
110
|
+
console.log(`Volume: ${Math.round(currentVolume * 100)}%`);
|
|
111
|
+
|
|
112
|
+
// Get user microphone input level
|
|
113
|
+
const inputLevel = agent.getInputVolume();
|
|
114
|
+
if (inputLevel > 0.1) {
|
|
115
|
+
showUserSpeakingIndicator();
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Microphone Control
|
|
120
|
+
|
|
121
|
+
```javascript
|
|
122
|
+
// Mute/unmute microphone
|
|
123
|
+
agent.setMicMuted(true); // Mute
|
|
124
|
+
agent.setMicMuted(false); // Unmute
|
|
125
|
+
|
|
126
|
+
// Check mute status
|
|
127
|
+
if (agent.isMicMuted()) {
|
|
128
|
+
showUnmutePrompt();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Toggle microphone
|
|
132
|
+
const currentMuted = agent.isMicMuted();
|
|
133
|
+
agent.setMicMuted(!currentMuted);
|
|
134
|
+
|
|
135
|
+
// Listen for microphone events
|
|
136
|
+
agent.on('micMuted', () => {
|
|
137
|
+
document.getElementById('micButton').classList.add('muted');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
agent.on('micUnmuted', () => {
|
|
141
|
+
document.getElementById('micButton').classList.remove('muted');
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Audio Visualization
|
|
146
|
+
|
|
147
|
+
Create real-time audio visualizers using frequency data:
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
// Input visualizer (user's microphone)
|
|
151
|
+
function createInputVisualizer() {
|
|
152
|
+
const canvas = document.getElementById('inputVisualizer');
|
|
153
|
+
const ctx = canvas.getContext('2d');
|
|
154
|
+
|
|
155
|
+
function draw() {
|
|
156
|
+
const frequencyData = agent.getInputByteFrequencyData();
|
|
157
|
+
|
|
158
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
159
|
+
const barWidth = canvas.width / frequencyData.length;
|
|
160
|
+
|
|
161
|
+
for (let i = 0; i < frequencyData.length; i++) {
|
|
162
|
+
const barHeight = (frequencyData[i] / 255) * canvas.height;
|
|
163
|
+
ctx.fillStyle = `hsl(${i * 2}, 70%, 60%)`;
|
|
164
|
+
ctx.fillRect(i * barWidth, canvas.height - barHeight, barWidth, barHeight);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
requestAnimationFrame(draw);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
draw();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Output visualizer (agent's voice)
|
|
174
|
+
function createOutputVisualizer() {
|
|
175
|
+
const canvas = document.getElementById('outputVisualizer');
|
|
176
|
+
const ctx = canvas.getContext('2d');
|
|
177
|
+
|
|
178
|
+
agent.on('speaking', () => {
|
|
179
|
+
function draw() {
|
|
180
|
+
const frequencyData = agent.getOutputByteFrequencyData();
|
|
181
|
+
|
|
182
|
+
if (frequencyData.length > 0) {
|
|
183
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
184
|
+
|
|
185
|
+
// Draw voice characteristics
|
|
186
|
+
for (let i = 0; i < frequencyData.length; i++) {
|
|
187
|
+
const barHeight = (frequencyData[i] / 255) * canvas.height;
|
|
188
|
+
ctx.fillStyle = `hsl(${240 + i}, 70%, 60%)`;
|
|
189
|
+
ctx.fillRect(i * 2, canvas.height - barHeight, 2, barHeight);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
requestAnimationFrame(draw);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
draw();
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
## Advanced Configuration Options
|
|
202
|
+
|
|
203
|
+
### Platform-Specific Optimizations
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
agent.start({
|
|
207
|
+
agentId: "your-agent-id",
|
|
208
|
+
|
|
209
|
+
// Optimize audio for iOS devices
|
|
210
|
+
preferHeadphonesForIosDevices: true,
|
|
211
|
+
|
|
212
|
+
// Platform-specific delays to prevent audio cutoff
|
|
213
|
+
connectionDelay: {
|
|
214
|
+
android: 3000, // Android needs longer delay for audio mode switching
|
|
215
|
+
ios: 500, // Shorter delay for iOS
|
|
216
|
+
default: 1000 // Default for other platforms
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
// Disable wake lock for battery optimization
|
|
220
|
+
disableWakeLock: false,
|
|
221
|
+
|
|
222
|
+
// User tracking
|
|
223
|
+
userId: "customer-12345"
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
90
227
|
## Events
|
|
91
228
|
|
|
92
229
|
During the conversation, the SDK emits events to update your application about the conversation status.
|
|
@@ -95,16 +232,16 @@ During the conversation, the SDK emits events to update your application about t
|
|
|
95
232
|
|
|
96
233
|
```javascript
|
|
97
234
|
agent.on("callStarted", () => {
|
|
98
|
-
|
|
235
|
+
console.log("Conversation has started!");
|
|
99
236
|
});
|
|
100
237
|
agent.on("callEnded", () => {
|
|
101
|
-
|
|
238
|
+
console.log("Conversation has ended!");
|
|
102
239
|
});
|
|
103
240
|
agent.on("callPaused", () => {
|
|
104
|
-
|
|
241
|
+
console.log("The conversation is paused");
|
|
105
242
|
});
|
|
106
243
|
agent.on("callResumed", () => {
|
|
107
|
-
|
|
244
|
+
console.log("Conversation has resumed");
|
|
108
245
|
});
|
|
109
246
|
```
|
|
110
247
|
|
|
@@ -112,10 +249,10 @@ agent.on("callResumed", () => {
|
|
|
112
249
|
|
|
113
250
|
```javascript
|
|
114
251
|
agent.on("speaking", () => {
|
|
115
|
-
|
|
252
|
+
console.log("The agent is speaking");
|
|
116
253
|
});
|
|
117
254
|
agent.on("listening", () => {
|
|
118
|
-
|
|
255
|
+
console.log("The agent is listening");
|
|
119
256
|
});
|
|
120
257
|
```
|
|
121
258
|
|
|
@@ -123,10 +260,10 @@ agent.on("listening", () => {
|
|
|
123
260
|
|
|
124
261
|
```javascript
|
|
125
262
|
agent.on("transcriptionReceived", (text) => {
|
|
126
|
-
|
|
263
|
+
console.log("User speech transcription received", text);
|
|
127
264
|
});
|
|
128
265
|
agent.on("answerReceived", (text) => {
|
|
129
|
-
|
|
266
|
+
console.log("Agent answer received", text);
|
|
130
267
|
});
|
|
131
268
|
```
|
|
132
269
|
|
|
@@ -134,10 +271,10 @@ agent.on("answerReceived", (text) => {
|
|
|
134
271
|
|
|
135
272
|
```javascript
|
|
136
273
|
agent.on("closed", () => {
|
|
137
|
-
|
|
274
|
+
console.log("Conversation was closed");
|
|
138
275
|
});
|
|
139
276
|
agent.on("error", (e) => {
|
|
140
|
-
|
|
277
|
+
console.log("Error was received", e);
|
|
141
278
|
});
|
|
142
279
|
```
|
|
143
280
|
|
|
@@ -148,46 +285,46 @@ The SDK provides comprehensive analytics for monitoring call quality, performanc
|
|
|
148
285
|
```javascript
|
|
149
286
|
// Real-time connection quality updates
|
|
150
287
|
agent.on("connectionQualityChanged", ({ quality, participant, metrics }) => {
|
|
151
|
-
|
|
288
|
+
console.log(`Connection quality: ${quality}`, metrics);
|
|
152
289
|
});
|
|
153
290
|
|
|
154
291
|
// Periodic analytics updates (every second during calls)
|
|
155
292
|
agent.on("analyticsUpdated", (analytics) => {
|
|
156
|
-
|
|
157
|
-
|
|
293
|
+
console.log("Call analytics:", analytics);
|
|
294
|
+
// Contains: connectionStats, audioMetrics, performanceMetrics, etc.
|
|
158
295
|
});
|
|
159
296
|
|
|
160
297
|
// Participant events
|
|
161
298
|
agent.on("participantConnected", (participant) => {
|
|
162
|
-
|
|
299
|
+
console.log("Participant joined:", participant.identity);
|
|
163
300
|
});
|
|
164
301
|
|
|
165
302
|
agent.on("participantDisconnected", (participant) => {
|
|
166
|
-
|
|
303
|
+
console.log("Participant left:", participant.identity);
|
|
167
304
|
});
|
|
168
305
|
|
|
169
306
|
// Track subscription events (audio/video streams)
|
|
170
307
|
agent.on("trackSubscribed", ({ track, participant, trackStats }) => {
|
|
171
|
-
|
|
308
|
+
console.log("New track:", track.kind, "from", participant);
|
|
172
309
|
});
|
|
173
310
|
|
|
174
311
|
agent.on("trackUnsubscribed", ({ track, participant }) => {
|
|
175
|
-
|
|
312
|
+
console.log("Track ended:", track.kind, "from", participant);
|
|
176
313
|
});
|
|
177
314
|
|
|
178
315
|
// Connection state changes
|
|
179
316
|
agent.on("reconnecting", () => {
|
|
180
|
-
|
|
317
|
+
console.log("Attempting to reconnect...");
|
|
181
318
|
});
|
|
182
319
|
|
|
183
320
|
agent.on("reconnected", () => {
|
|
184
|
-
|
|
321
|
+
console.log("Successfully reconnected");
|
|
185
322
|
});
|
|
186
323
|
|
|
187
324
|
// Custom events from agents
|
|
188
325
|
agent.on("customEvent", (eventType, eventData, metadata) => {
|
|
189
|
-
|
|
190
|
-
|
|
326
|
+
console.log(`Custom event: ${eventType}`, eventData);
|
|
327
|
+
// Examples: flow_navigation, tool_execution, agent_state_change
|
|
191
328
|
});
|
|
192
329
|
```
|
|
193
330
|
|
|
@@ -195,6 +332,17 @@ agent.on("customEvent", (eventType, eventData, metadata) => {
|
|
|
195
332
|
|
|
196
333
|
The SDK provides comprehensive real-time analytics for monitoring call quality, performance metrics, and custom agent events. Access analytics data through both synchronous methods and event-driven updates.
|
|
197
334
|
|
|
335
|
+
### Analytics Architecture
|
|
336
|
+
|
|
337
|
+
The SDK uses a clean modular design with four specialized components:
|
|
338
|
+
|
|
339
|
+
- **Connection Management**: Handles room connections, participants, and network state
|
|
340
|
+
- **Analytics Engine**: Processes WebRTC statistics and performance metrics
|
|
341
|
+
- **Audio Management**: Manages audio tracks, volume control, and quality monitoring
|
|
342
|
+
- **Tool Registry**: Handles RPC method registration and client-side tool execution
|
|
343
|
+
|
|
344
|
+
Access analytics data through both synchronous methods and event-driven updates.
|
|
345
|
+
|
|
198
346
|
### Synchronous Analytics Methods
|
|
199
347
|
|
|
200
348
|
Get real-time analytics data instantly for dashboards and monitoring:
|
|
@@ -278,16 +426,18 @@ const analytics = agent.getCallAnalytics();
|
|
|
278
426
|
console.log(analytics);
|
|
279
427
|
/*
|
|
280
428
|
{
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
429
|
+
connectionStats: { latency: 45, packetLoss: 0.1, quality: 'good', ... },
|
|
430
|
+
audioMetrics: { userAudioLevel: 0.8, agentAudioLevel: 0.3, ... },
|
|
431
|
+
performanceMetrics: { callDuration: 60000, responseTime: 1200, ... },
|
|
432
|
+
participants: [{ identity: 'agent', sid: 'participant-sid', ... }],
|
|
433
|
+
trackStats: { totalTracks: 2, activeTracks: 2, ... },
|
|
434
|
+
callStats: { connectionAttempts: 1, packetsLost: 0, ... },
|
|
435
|
+
metadata: {
|
|
436
|
+
callStartTime: 1638360000000,
|
|
437
|
+
isConnected: true,
|
|
438
|
+
isPaused: false,
|
|
439
|
+
volume: 1.0
|
|
440
|
+
}
|
|
291
441
|
}
|
|
292
442
|
*/
|
|
293
443
|
```
|
|
@@ -299,25 +449,31 @@ Build live monitoring dashboards using the analytics data:
|
|
|
299
449
|
```javascript
|
|
300
450
|
// Update dashboard every second
|
|
301
451
|
const updateDashboard = () => {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
452
|
+
const stats = agent.getConnectionStats();
|
|
453
|
+
const audio = agent.getAudioLevels();
|
|
454
|
+
const performance = agent.getPerformanceMetrics();
|
|
455
|
+
|
|
456
|
+
// Update UI elements
|
|
457
|
+
document.getElementById("latency").textContent = `${stats.latency}ms`;
|
|
458
|
+
document.getElementById("quality").textContent = stats.quality;
|
|
459
|
+
document.getElementById("duration").textContent = `${Math.floor(
|
|
460
|
+
performance.callDuration / 1000
|
|
461
|
+
)}s`;
|
|
462
|
+
document.getElementById("user-audio").style.width = `${
|
|
463
|
+
audio.userAudioLevel * 100
|
|
464
|
+
}%`;
|
|
465
|
+
document.getElementById("agent-audio").style.width = `${
|
|
466
|
+
audio.agentAudioLevel * 100
|
|
467
|
+
}%`;
|
|
312
468
|
};
|
|
313
469
|
|
|
314
470
|
// Start dashboard updates when call begins
|
|
315
|
-
agent.on(
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
471
|
+
agent.on("callStarted", () => {
|
|
472
|
+
const dashboardInterval = setInterval(updateDashboard, 1000);
|
|
473
|
+
|
|
474
|
+
agent.on("callEnded", () => {
|
|
475
|
+
clearInterval(dashboardInterval);
|
|
476
|
+
});
|
|
321
477
|
});
|
|
322
478
|
```
|
|
323
479
|
|
|
@@ -327,30 +483,40 @@ Track custom events from your voice agents:
|
|
|
327
483
|
|
|
328
484
|
```javascript
|
|
329
485
|
agent.on("customEvent", (eventType, eventData, metadata) => {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
486
|
+
switch (eventType) {
|
|
487
|
+
case "flow_navigation":
|
|
488
|
+
console.log("Agent navigated:", eventData.from, "->", eventData.to);
|
|
489
|
+
// Track conversation flow
|
|
490
|
+
break;
|
|
491
|
+
|
|
492
|
+
case "tool_execution":
|
|
493
|
+
console.log(
|
|
494
|
+
"Tool called:",
|
|
495
|
+
eventData.toolName,
|
|
496
|
+
"Result:",
|
|
497
|
+
eventData.success
|
|
498
|
+
);
|
|
499
|
+
// Monitor tool usage
|
|
500
|
+
break;
|
|
501
|
+
|
|
502
|
+
case "agent_state_change":
|
|
503
|
+
console.log("Agent state:", eventData.state);
|
|
504
|
+
// Track agent behavior
|
|
505
|
+
break;
|
|
506
|
+
|
|
507
|
+
case "user_intent_detected":
|
|
508
|
+
console.log(
|
|
509
|
+
"User intent:",
|
|
510
|
+
eventData.intent,
|
|
511
|
+
"Confidence:",
|
|
512
|
+
eventData.confidence
|
|
513
|
+
);
|
|
514
|
+
// Analyze user intent
|
|
515
|
+
break;
|
|
516
|
+
|
|
517
|
+
default:
|
|
518
|
+
console.log("Custom event:", eventType, eventData);
|
|
519
|
+
}
|
|
354
520
|
});
|
|
355
521
|
```
|
|
356
522
|
|
|
@@ -360,7 +526,7 @@ The SDK accepts optional configuration parameters:
|
|
|
360
526
|
|
|
361
527
|
```javascript
|
|
362
528
|
const agent = new HamsaVoiceAgent("YOUR_API_KEY", {
|
|
363
|
-
|
|
529
|
+
API_URL: "https://api.tryhamsa.com", // API endpoint (default)
|
|
364
530
|
});
|
|
365
531
|
```
|
|
366
532
|
|
|
@@ -370,29 +536,29 @@ You can register client-side tools that the agent can call during conversations:
|
|
|
370
536
|
|
|
371
537
|
```javascript
|
|
372
538
|
const tools = [
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
539
|
+
{
|
|
540
|
+
function_name: "getUserInfo",
|
|
541
|
+
description: "Get user information",
|
|
542
|
+
parameters: [
|
|
543
|
+
{
|
|
544
|
+
name: "userId",
|
|
545
|
+
type: "string",
|
|
546
|
+
description: "User ID to look up",
|
|
547
|
+
},
|
|
548
|
+
],
|
|
549
|
+
required: ["userId"],
|
|
550
|
+
fn: async (userId) => {
|
|
551
|
+
// Your tool implementation
|
|
552
|
+
const userInfo = await fetchUserInfo(userId);
|
|
553
|
+
return userInfo;
|
|
554
|
+
},
|
|
555
|
+
},
|
|
390
556
|
];
|
|
391
557
|
|
|
392
558
|
agent.start({
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
559
|
+
agentId: "YOUR_AGENT_ID",
|
|
560
|
+
tools: tools,
|
|
561
|
+
voiceEnablement: true,
|
|
396
562
|
});
|
|
397
563
|
```
|
|
398
564
|
|
|
@@ -404,69 +570,131 @@ If you're upgrading from a previous version, see the [Migration Guide](./MIGRATI
|
|
|
404
570
|
|
|
405
571
|
This SDK supports modern browsers with WebRTC capabilities:
|
|
406
572
|
|
|
407
|
-
-
|
|
408
|
-
-
|
|
409
|
-
-
|
|
410
|
-
-
|
|
573
|
+
- Chrome 60+
|
|
574
|
+
- Firefox 60+
|
|
575
|
+
- Safari 12+
|
|
576
|
+
- Edge 79+
|
|
411
577
|
|
|
412
578
|
## TypeScript Support
|
|
413
579
|
|
|
414
580
|
The SDK includes comprehensive TypeScript definitions with detailed analytics interfaces:
|
|
415
581
|
|
|
416
582
|
```typescript
|
|
417
|
-
import {
|
|
583
|
+
import {
|
|
584
|
+
HamsaVoiceAgent,
|
|
585
|
+
CallAnalyticsResult,
|
|
586
|
+
ParticipantData,
|
|
587
|
+
CustomEventMetadata,
|
|
588
|
+
} from "@hamsa-ai/voice-agents-sdk";
|
|
418
589
|
|
|
419
590
|
// All analytics methods return strongly typed data
|
|
420
591
|
const agent = new HamsaVoiceAgent("API_KEY");
|
|
421
592
|
|
|
422
|
-
// TypeScript will provide autocomplete and type checking
|
|
423
|
-
agent.
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
593
|
+
// TypeScript will provide full autocomplete and type checking for all methods
|
|
594
|
+
const connectionStats = agent.getConnectionStats(); // ConnectionStatsResult | null
|
|
595
|
+
const audioLevels = agent.getAudioLevels(); // AudioLevelsResult | null
|
|
596
|
+
const performance = agent.getPerformanceMetrics(); // PerformanceMetricsResult | null
|
|
597
|
+
const participants = agent.getParticipants(); // ParticipantData[]
|
|
598
|
+
const trackStats = agent.getTrackStats(); // TrackStatsResult | null
|
|
599
|
+
const analytics = agent.getCallAnalytics(); // CallAnalyticsResult | null
|
|
600
|
+
|
|
601
|
+
// Advanced audio control methods
|
|
602
|
+
const outputVolume = agent.getOutputVolume(); // number
|
|
603
|
+
const inputVolume = agent.getInputVolume(); // number
|
|
604
|
+
const isMuted = agent.isMicMuted(); // boolean
|
|
605
|
+
const inputFreqData = agent.getInputByteFrequencyData(); // Uint8Array
|
|
606
|
+
const outputFreqData = agent.getOutputByteFrequencyData(); // Uint8Array
|
|
607
|
+
|
|
608
|
+
// Strongly typed start options with all advanced features
|
|
609
|
+
await agent.start({
|
|
610
|
+
agentId: "agent-id",
|
|
611
|
+
voiceEnablement: true,
|
|
612
|
+
userId: "user-123",
|
|
613
|
+
params: {
|
|
614
|
+
userName: "John Doe",
|
|
615
|
+
sessionId: "session-456"
|
|
616
|
+
},
|
|
617
|
+
preferHeadphonesForIosDevices: true,
|
|
618
|
+
connectionDelay: {
|
|
619
|
+
android: 3000,
|
|
620
|
+
ios: 500,
|
|
621
|
+
default: 1000
|
|
622
|
+
},
|
|
623
|
+
disableWakeLock: false
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
// Strongly typed event handlers
|
|
627
|
+
agent.on("analyticsUpdated", (analytics: CallAnalyticsResult) => {
|
|
628
|
+
console.log(analytics.connectionStats.latency); // number
|
|
629
|
+
console.log(analytics.audioMetrics.userAudioLevel); // number
|
|
630
|
+
console.log(analytics.performanceMetrics.callDuration); // number
|
|
631
|
+
console.log(analytics.participants.length); // number
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
// Audio control events
|
|
635
|
+
agent.on("micMuted", () => {
|
|
636
|
+
console.log("Microphone was muted");
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
agent.on("micUnmuted", () => {
|
|
640
|
+
console.log("Microphone was unmuted");
|
|
427
641
|
});
|
|
428
642
|
|
|
429
643
|
// Strongly typed custom events
|
|
430
|
-
agent.on(
|
|
644
|
+
agent.on(
|
|
645
|
+
"customEvent",
|
|
646
|
+
(eventType: string, eventData: any, metadata: CustomEventMetadata) => {
|
|
431
647
|
console.log(metadata.timestamp); // number
|
|
432
648
|
console.log(metadata.participant); // string
|
|
649
|
+
}
|
|
650
|
+
);
|
|
651
|
+
|
|
652
|
+
// Strongly typed participant events
|
|
653
|
+
agent.on("participantConnected", (participant: ParticipantData) => {
|
|
654
|
+
console.log(participant.identity); // string
|
|
655
|
+
console.log(participant.connectionTime); // number
|
|
433
656
|
});
|
|
434
657
|
```
|
|
435
658
|
|
|
436
659
|
## Use Cases
|
|
437
660
|
|
|
438
661
|
### Real-time Call Quality Monitoring
|
|
662
|
+
|
|
439
663
|
```javascript
|
|
440
664
|
agent.on("connectionQualityChanged", ({ quality, metrics }) => {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
665
|
+
if (quality === "poor") {
|
|
666
|
+
showNetworkWarning();
|
|
667
|
+
logQualityIssue(metrics);
|
|
668
|
+
}
|
|
445
669
|
});
|
|
446
670
|
```
|
|
447
671
|
|
|
448
672
|
### Analytics Dashboard
|
|
673
|
+
|
|
449
674
|
```javascript
|
|
450
675
|
const analytics = agent.getCallAnalytics();
|
|
451
676
|
sendToAnalytics({
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
677
|
+
callDuration: analytics.callDuration,
|
|
678
|
+
audioQuality: analytics.audioMetrics,
|
|
679
|
+
participantCount: analytics.participants.length,
|
|
680
|
+
performance: analytics.performanceMetrics,
|
|
456
681
|
});
|
|
457
682
|
```
|
|
458
683
|
|
|
459
684
|
### Conversation Flow Analysis
|
|
685
|
+
|
|
460
686
|
```javascript
|
|
461
687
|
agent.on("customEvent", (eventType, data) => {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
688
|
+
if (eventType === "flow_navigation") {
|
|
689
|
+
trackConversationFlow(data.from, data.to);
|
|
690
|
+
optimizeAgentResponses(data);
|
|
691
|
+
}
|
|
466
692
|
});
|
|
467
693
|
```
|
|
468
694
|
|
|
469
695
|
## Dependencies
|
|
470
696
|
|
|
471
|
-
-
|
|
472
|
-
-
|
|
697
|
+
- **livekit-client v2.15.4**: Real-time communication infrastructure
|
|
698
|
+
- **events v3.3.0**: EventEmitter for browser compatibility
|
|
699
|
+
|
|
700
|
+
The SDK uses LiveKit's native WebRTC capabilities for high-quality real-time audio communication and comprehensive analytics.
|