@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hamsa-ai/voice-agents-sdk",
3
- "version": "0.4.0-beta.1",
3
+ "version": "0.4.0-beta.2",
4
4
  "description": "Hamsa AI - Voice Agents JavaScript SDK",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -21,9 +21,9 @@
21
21
  ],
22
22
  "scripts": {
23
23
  "clean": "rimraf dist types",
24
- "build:types": "tsc",
25
- "build:webpack": "webpack --config webpack.config.js",
26
- "build": "npm run clean && npm run build:types && npm run build:webpack",
24
+ "build:types": "tsc -p tsconfig.declarations.json",
25
+ "build:rollup": "rollup -c",
26
+ "build": "npm run clean && npm run build:types && npm run build:rollup",
27
27
  "test": "jest",
28
28
  "test:watch": "jest --watch",
29
29
  "prepare": "npm run build"
@@ -33,20 +33,24 @@
33
33
  "devDependencies": {
34
34
  "@babel/core": "^7.23.0",
35
35
  "@babel/preset-env": "^7.23.0",
36
- "audio-worklet-loader": "^1.1.0",
36
+ "@babel/preset-typescript": "^7.23.0",
37
+ "@biomejs/biome": "^2.2.0",
38
+ "@rollup/plugin-commonjs": "^28.0.6",
39
+ "@rollup/plugin-node-resolve": "^16.0.1",
40
+ "@rollup/plugin-terser": "^0.4.4",
41
+ "@rollup/plugin-typescript": "^12.1.4",
42
+ "@types/jest": "^30.0.0",
37
43
  "babel-jest": "^29.7.0",
38
- "babel-loader": "^9.1.3",
39
44
  "buffer": "^6.0.3",
40
- "css-loader": "^7.1.2",
41
- "file-loader": "^6.2.0",
42
45
  "jest": "^29.7.0",
43
46
  "jest-environment-jsdom": "^29.7.0",
47
+ "lefthook": "^1.12.3",
48
+ "lint-staged": "^16.1.5",
44
49
  "rimraf": "^6.0.1",
45
- "style-loader": "^4.0.0",
50
+ "rollup": "^4.48.1",
51
+ "ts-jest": "^29.4.1",
46
52
  "typescript": "^5.5.4",
47
- "webpack": "^5.91.0",
48
- "webpack-cli": "^5.1.4",
49
- "webpack-node-externals": "^3.0.0"
53
+ "ultracite": "^5.2.3"
50
54
  },
51
55
  "dependencies": {
52
56
  "events": "^3.3.0",
@@ -69,5 +73,10 @@
69
73
  "bugs": {
70
74
  "url": "https://github.com/hamsa-ai/voice-agents-sdk/issues"
71
75
  },
72
- "homepage": "https://github.com/hamsa-ai/voice-agents-sdk#readme"
76
+ "homepage": "https://github.com/hamsa-ai/voice-agents-sdk#readme",
77
+ "lint-staged": {
78
+ "*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}": [
79
+ "npx ultracite format"
80
+ ]
81
+ }
73
82
  }
@@ -0,0 +1,370 @@
1
+ /**
2
+ * LiveKitAnalytics - Advanced analytics engine for voice agent communication
3
+ *
4
+ * This class provides comprehensive real-time analytics for voice agent conversations,
5
+ * collecting and processing WebRTC statistics, performance metrics, audio quality data,
6
+ * and connection health information. It serves as the analytics backbone for monitoring
7
+ * call quality, user engagement, and system performance.
8
+ *
9
+ * Key features:
10
+ * - Real-time WebRTC statistics collection and processing
11
+ * - Connection quality monitoring with automatic quality assessment
12
+ * - Audio level tracking and speaking time analytics
13
+ * - Performance metrics including response times and latency measurements
14
+ * - Periodic analytics updates with configurable intervals
15
+ * - Event-driven architecture for real-time monitoring dashboards
16
+ * - Automatic cleanup and resource management
17
+ *
18
+ * Analytics Categories:
19
+ *
20
+ * **Connection Analytics:**
21
+ * - Network latency and jitter measurements
22
+ * - Packet loss detection and monitoring
23
+ * - Connection quality assessment (excellent/good/poor/lost)
24
+ * - Bandwidth utilization tracking
25
+ * - Connection attempt and reconnection statistics
26
+ *
27
+ * **Audio Analytics:**
28
+ * - Real-time audio level monitoring for user and agent
29
+ * - Speaking time tracking for conversation analysis
30
+ * - Audio dropout detection and counting
31
+ * - Echo cancellation status monitoring
32
+ * - Voice activity detection and timing
33
+ *
34
+ * **Performance Analytics:**
35
+ * - Response time measurements for agent interactions
36
+ * - Call duration tracking with millisecond precision
37
+ * - Connection establishment time monitoring
38
+ * - Reconnection frequency and success rates
39
+ * - Network latency impact on call quality
40
+ *
41
+ * **Usage Patterns:**
42
+ *
43
+ * @example Real-time Quality Monitoring
44
+ * ```typescript
45
+ * const analytics = new LiveKitAnalytics();
46
+ *
47
+ * // Listen for quality changes
48
+ * analytics.on('connectionQualityChanged', ({ quality, metrics }) => {
49
+ * if (quality === 'poor') {
50
+ * showNetworkWarning(metrics);
51
+ * logQualityIssue(metrics);
52
+ * }
53
+ * });
54
+ *
55
+ * // Monitor periodic updates
56
+ * analytics.on('analyticsUpdated', (data) => {
57
+ * updateDashboard({
58
+ * latency: data.connectionStats.latency,
59
+ * audioLevels: data.audioMetrics,
60
+ * callDuration: data.performanceMetrics.callDuration
61
+ * });
62
+ * });
63
+ *
64
+ * // Start collection
65
+ * analytics.setRoom(liveKitRoom);
66
+ * analytics.setConnectionState(true, Date.now());
67
+ * analytics.startAnalyticsCollection();
68
+ * ```
69
+ *
70
+ * @example Analytics Dashboard Integration
71
+ * ```typescript
72
+ * // Get comprehensive analytics snapshot
73
+ * const fullAnalytics = analytics.getCallAnalytics(
74
+ * participants,
75
+ * trackStats,
76
+ * currentVolume,
77
+ * isPaused
78
+ * );
79
+ *
80
+ * // Send to analytics service
81
+ * analyticsService.recordCall({
82
+ * sessionId: generateSessionId(),
83
+ * timestamp: Date.now(),
84
+ * metrics: fullAnalytics,
85
+ * agentId: currentAgentId
86
+ * });
87
+ *
88
+ * // Real-time metrics display
89
+ * const connectionStats = analytics.getConnectionStats();
90
+ * const audioLevels = analytics.getAudioLevels();
91
+ * const performance = analytics.getPerformanceMetrics();
92
+ *
93
+ * updateUI({
94
+ * quality: connectionStats.quality,
95
+ * latency: connectionStats.latency,
96
+ * userSpeaking: audioLevels.userAudioLevel > 0.1,
97
+ * agentSpeaking: audioLevels.agentAudioLevel > 0.1,
98
+ * callDuration: performance.callDuration
99
+ * });
100
+ * ```
101
+ *
102
+ * @example Quality Issue Detection
103
+ * ```typescript
104
+ * // Monitor for quality degradation
105
+ * analytics.on('connectionQualityChanged', ({ quality, metrics }) => {
106
+ * switch (quality) {
107
+ * case 'poor':
108
+ * notifyUser('Network quality is poor. Consider switching networks.');
109
+ * logMetric('quality_degradation', metrics);
110
+ * break;
111
+ * case 'lost':
112
+ * handleConnectionLoss();
113
+ * attemptReconnection();
114
+ * break;
115
+ * }
116
+ * });
117
+ *
118
+ * // Check for high latency
119
+ * const stats = analytics.getConnectionStats();
120
+ * if (stats.latency > 300) {
121
+ * showLatencyWarning(stats.latency);
122
+ * }
123
+ *
124
+ * // Monitor packet loss
125
+ * if (stats.packetLoss > 5) {
126
+ * reportNetworkIssue('high_packet_loss', stats);
127
+ * }
128
+ * ```
129
+ *
130
+ * Technical Implementation:
131
+ * - Uses LiveKit's native WebRTC statistics when available
132
+ * - Implements fallback quality estimation based on ConnectionQuality enum
133
+ * - Collects analytics every 5 seconds (configurable via ANALYTICS_COLLECTION_INTERVAL)
134
+ * - Maintains real-time audio activity tracking with timestamp precision
135
+ * - Provides thread-safe cleanup and resource management
136
+ * - Emits structured events for easy integration with monitoring systems
137
+ */
138
+ import { EventEmitter } from 'events';
139
+ import { ConnectionQuality, type Participant, type Room } from 'livekit-client';
140
+ import type { AudioLevelsResult, AudioMetrics, CallAnalyticsResult, CallStats, ConnectionMetrics, ConnectionStatsResult, ParticipantData, PerformanceMetrics, PerformanceMetricsResult, TrackStatsResult } from './types';
141
+ /**
142
+ * LiveKitAnalytics class extending EventEmitter for real-time analytics
143
+ *
144
+ * Provides comprehensive analytics collection and processing for voice agent
145
+ * conversations, including connection quality, audio metrics, and performance data.
146
+ */
147
+ export declare class LiveKitAnalytics extends EventEmitter {
148
+ #private;
149
+ /** Call-level statistics including connection attempts, packet counts, and quality metrics */
150
+ callStats: CallStats;
151
+ /** Network connection metrics including latency, packet loss, and quality ratings */
152
+ connectionMetrics: ConnectionMetrics;
153
+ /** Audio-related metrics for both user and agent including levels and speaking time */
154
+ audioMetrics: AudioMetrics;
155
+ /** Performance metrics including response times, latency, and call duration data */
156
+ performanceMetrics: PerformanceMetrics;
157
+ /** Timer handle for periodic analytics collection, null when not collecting */
158
+ analyticsInterval: NodeJS.Timeout | null;
159
+ /** Timestamp when agent started speaking for calculating speaking duration */
160
+ lastAgentSpeakStart: number | null;
161
+ /** Timestamp when user started speaking for calculating speaking duration */
162
+ lastUserSpeakStart: number | null;
163
+ /** Unix timestamp when the call/session started for duration calculations */
164
+ callStartTime: number | null;
165
+ /** Reference to the LiveKit room for accessing WebRTC statistics */
166
+ private room;
167
+ /** Current connection state flag for controlling analytics collection */
168
+ private isConnected;
169
+ /**
170
+ * Creates a new LiveKitAnalytics instance
171
+ *
172
+ * Initializes all metric structures to default values and prepares
173
+ * the analytics system for data collection. The instance is ready
174
+ * to begin collection once a room reference is provided.
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * const analytics = new LiveKitAnalytics();
179
+ *
180
+ * // Set up event listeners
181
+ * analytics.on('connectionQualityChanged', handleQualityChange);
182
+ * analytics.on('analyticsUpdated', updateDashboard);
183
+ *
184
+ * // Configure for a specific room
185
+ * analytics.setRoom(liveKitRoom);
186
+ * analytics.setConnectionState(true, Date.now());
187
+ * analytics.startAnalyticsCollection();
188
+ * ```
189
+ */
190
+ constructor();
191
+ /**
192
+ * Sets the LiveKit room reference for analytics data collection
193
+ *
194
+ * Provides the analytics system with access to the LiveKit room instance
195
+ * for collecting WebRTC statistics and monitoring connection quality.
196
+ * This is typically called by the LiveKitManager when a connection is established.
197
+ *
198
+ * @param room - LiveKit room instance or null to clear the reference
199
+ *
200
+ * @example
201
+ * ```typescript
202
+ * const room = new Room();
203
+ * await room.connect(url, token);
204
+ *
205
+ * analytics.setRoom(room); // Enable analytics collection
206
+ * analytics.setRoom(null); // Disable collection
207
+ * ```
208
+ */
209
+ setRoom(room: Room | null): void;
210
+ /**
211
+ * Updates the connection state and optionally sets the call start time
212
+ *
213
+ * Controls whether analytics collection is active and records when the
214
+ * call session began for accurate duration calculations. The call start
215
+ * time is used for all performance metrics that depend on session duration.
216
+ *
217
+ * @param isConnected - Whether the connection is currently active
218
+ * @param callStartTime - Unix timestamp when the call started (optional)
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * // Connection established
223
+ * analytics.setConnectionState(true, Date.now());
224
+ *
225
+ * // Connection lost
226
+ * analytics.setConnectionState(false);
227
+ *
228
+ * // Reconnection successful (preserve original start time)
229
+ * analytics.setConnectionState(true);
230
+ * ```
231
+ */
232
+ setConnectionState(isConnected: boolean, callStartTime?: number | null): void;
233
+ /**
234
+ * Updates connection attempt statistics for reliability tracking
235
+ *
236
+ * Tracks the number of initial connection attempts and reconnection
237
+ * attempts for monitoring connection reliability and user experience.
238
+ * These metrics help identify network stability issues.
239
+ *
240
+ * @param connectionAttempts - Total number of initial connection attempts
241
+ * @param reconnectionAttempts - Total number of reconnection attempts
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * // After initial connection attempt
246
+ * analytics.updateConnectionStats(1, 0);
247
+ *
248
+ * // After reconnection
249
+ * analytics.updateConnectionStats(1, 1);
250
+ *
251
+ * // Multiple reconnection attempts
252
+ * analytics.updateConnectionStats(1, 3);
253
+ * ```
254
+ */
255
+ updateConnectionStats(connectionAttempts: number, reconnectionAttempts: number): void;
256
+ /**
257
+ * Updates real-time participant and track counts for session monitoring
258
+ *
259
+ * Tracks the current number of participants in the conversation and
260
+ * active audio/video tracks for capacity monitoring and analytics.
261
+ * These counts are updated whenever participants join/leave or tracks change.
262
+ *
263
+ * @param participantCount - Current number of participants in the room
264
+ * @param trackCount - Current number of active tracks (audio/video streams)
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * // Initial state: user only
269
+ * analytics.updateCounts(1, 0);
270
+ *
271
+ * // Agent joins with audio track
272
+ * analytics.updateCounts(2, 1);
273
+ *
274
+ * // Additional participant joins
275
+ * analytics.updateCounts(3, 2);
276
+ * ```
277
+ */
278
+ updateCounts(participantCount: number, trackCount: number): void;
279
+ /**
280
+ * Records the time taken to establish the WebRTC connection
281
+ *
282
+ * Captures the duration from connection initiation to successful establishment
283
+ * for performance monitoring and optimization. This metric helps identify
284
+ * connection setup bottlenecks and network performance issues.
285
+ *
286
+ * @param time - Time in milliseconds to establish the connection
287
+ *
288
+ * @example
289
+ * ```typescript
290
+ * const startTime = Date.now();
291
+ * await room.connect(url, token);
292
+ * const establishTime = Date.now() - startTime;
293
+ *
294
+ * analytics.setConnectionEstablishedTime(establishTime);
295
+ * ```
296
+ */
297
+ setConnectionEstablishedTime(time: number): void;
298
+ /**
299
+ * Begins periodic analytics data collection and event emission
300
+ *
301
+ * Starts a recurring timer that collects WebRTC statistics, processes metrics,
302
+ * and emits analytics updates every 5 seconds. This enables real-time monitoring
303
+ * dashboards and automated quality detection systems. Automatically stops any
304
+ * existing collection before starting new collection.
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * // Start collection when connection is established
309
+ * analytics.setRoom(room);
310
+ * analytics.setConnectionState(true, Date.now());
311
+ * analytics.startAnalyticsCollection();
312
+ *
313
+ * // Listen for periodic updates
314
+ * analytics.on('analyticsUpdated', (data) => {
315
+ * updateDashboard(data);
316
+ * checkQualityThresholds(data);
317
+ * });
318
+ * ```
319
+ */
320
+ startAnalyticsCollection(): void;
321
+ /**
322
+ * Stops periodic analytics collection and clears the collection timer
323
+ *
324
+ * Terminates the recurring analytics collection, stopping all periodic
325
+ * data gathering and event emission. This is typically called when
326
+ * disconnecting or when analytics are no longer needed.
327
+ *
328
+ * @example
329
+ * ```typescript
330
+ * // Stop collection when disconnecting
331
+ * analytics.stopAnalyticsCollection();
332
+ *
333
+ * // Or stop temporarily for resource conservation
334
+ * if (backgroundMode) {
335
+ * analytics.stopAnalyticsCollection();
336
+ * }
337
+ * ```
338
+ */
339
+ stopAnalyticsCollection(): void;
340
+ /**
341
+ * Handles connection quality changes
342
+ */
343
+ handleConnectionQualityChanged(quality: ConnectionQuality, participant: Participant): void;
344
+ /**
345
+ * Handles audio playback status changes
346
+ */
347
+ handleAudioPlaybackChanged(playing: boolean): void;
348
+ /**
349
+ * Gets current connection statistics
350
+ */
351
+ getConnectionStats(): ConnectionStatsResult;
352
+ /**
353
+ * Gets current audio levels and metrics
354
+ */
355
+ getAudioLevels(): AudioLevelsResult;
356
+ /**
357
+ * Gets current performance metrics
358
+ */
359
+ getPerformanceMetrics(): PerformanceMetricsResult;
360
+ /**
361
+ * Gets comprehensive call analytics
362
+ */
363
+ getCallAnalytics(participants: ParticipantData[], trackStats: TrackStatsResult, volume: number, isPaused: boolean): CallAnalyticsResult & {
364
+ callDuration: number;
365
+ };
366
+ /**
367
+ * Cleans up analytics resources
368
+ */
369
+ cleanup(): void;
370
+ }