@anganyai/voice-sdk 0.0.1

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.
@@ -0,0 +1,1708 @@
1
+ /**
2
+ * Core type definitions for Angany Voice SDK
3
+ */
4
+ /**
5
+ * SDK configuration options
6
+ */
7
+ interface VoiceConfig {
8
+ /**
9
+ * The base URL of the Angany API
10
+ * @default 'https://api.angany.ai'
11
+ */
12
+ apiUrl: string;
13
+ /**
14
+ * The OIDC issuer URL
15
+ * @default Same as apiUrl
16
+ */
17
+ issuer?: string;
18
+ /**
19
+ * Enable debug mode for detailed logging
20
+ * @default false
21
+ */
22
+ debug?: boolean;
23
+ /**
24
+ * Logging level
25
+ * @default 'warn'
26
+ */
27
+ logLevel?: LogLevel;
28
+ /**
29
+ * Custom logger instance
30
+ */
31
+ logger?: Logger;
32
+ /**
33
+ * Request timeout in milliseconds
34
+ * @default 30000
35
+ */
36
+ timeout?: number;
37
+ /**
38
+ * Retry configuration
39
+ */
40
+ retry?: RetryConfig;
41
+ /**
42
+ * Custom headers to include in all requests
43
+ */
44
+ headers?: Record<string, string>;
45
+ /**
46
+ * Platform-specific configuration
47
+ */
48
+ platform?: PlatformConfig;
49
+ }
50
+ /**
51
+ * Log levels
52
+ */
53
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
54
+ /**
55
+ * Logger interface
56
+ */
57
+ interface Logger {
58
+ debug(message: string, context?: Record<string, unknown>): void;
59
+ info(message: string, context?: Record<string, unknown>): void;
60
+ warn(message: string, context?: Record<string, unknown>): void;
61
+ error(message: string, context?: Record<string, unknown>): void;
62
+ }
63
+ /**
64
+ * Retry configuration
65
+ */
66
+ interface RetryConfig {
67
+ /**
68
+ * Maximum number of retry attempts
69
+ * @default 3
70
+ */
71
+ maxAttempts?: number;
72
+ /**
73
+ * Initial delay in milliseconds
74
+ * @default 1000
75
+ */
76
+ initialDelay?: number;
77
+ /**
78
+ * Maximum delay in milliseconds
79
+ * @default 30000
80
+ */
81
+ maxDelay?: number;
82
+ /**
83
+ * Backoff multiplier
84
+ * @default 2
85
+ */
86
+ multiplier?: number;
87
+ /**
88
+ * Jitter factor (0-1)
89
+ * @default 0.1
90
+ */
91
+ jitter?: number;
92
+ }
93
+ /**
94
+ * Platform-specific configuration
95
+ */
96
+ interface PlatformConfig {
97
+ /**
98
+ * React Native specific config
99
+ */
100
+ reactNative?: {
101
+ /**
102
+ * InCallManager configuration
103
+ */
104
+ inCallManager?: Record<string, unknown>;
105
+ };
106
+ /**
107
+ * Node.js specific config
108
+ */
109
+ node?: {
110
+ /**
111
+ * HTTP agent configuration
112
+ */
113
+ agent?: unknown;
114
+ };
115
+ /**
116
+ * Web specific config
117
+ */
118
+ web?: {
119
+ /**
120
+ * WebRTC constraints
121
+ */
122
+ rtcConfiguration?: RTCConfiguration;
123
+ };
124
+ }
125
+ /**
126
+ * Voice resource information
127
+ */
128
+ interface VoiceResource {
129
+ /**
130
+ * Unique identifier for the resource
131
+ */
132
+ id: string;
133
+ /**
134
+ * Display name of the resource
135
+ */
136
+ name: string;
137
+ /**
138
+ * Description of the resource
139
+ */
140
+ description?: string;
141
+ /**
142
+ * Resource type
143
+ */
144
+ type: 'agent' | 'assistant' | 'custom';
145
+ /**
146
+ * Resource capabilities
147
+ */
148
+ capabilities?: string[];
149
+ /**
150
+ * Resource metadata
151
+ */
152
+ metadata?: Record<string, unknown>;
153
+ /**
154
+ * Whether the resource is currently available
155
+ */
156
+ available: boolean;
157
+ /**
158
+ * Resource configuration
159
+ */
160
+ config?: ResourceConfig;
161
+ }
162
+ /**
163
+ * Resource configuration
164
+ */
165
+ interface ResourceConfig {
166
+ /**
167
+ * SIP extension for this resource
168
+ */
169
+ extension?: string;
170
+ /**
171
+ * Supported languages
172
+ */
173
+ languages?: string[];
174
+ /**
175
+ * Voice configuration
176
+ */
177
+ voice?: {
178
+ /**
179
+ * Voice ID
180
+ */
181
+ id?: string;
182
+ /**
183
+ * Voice settings
184
+ */
185
+ settings?: Record<string, unknown>;
186
+ };
187
+ /**
188
+ * Custom configuration
189
+ */
190
+ custom?: Record<string, unknown>;
191
+ }
192
+
193
+ /**
194
+ * Simple event emitter implementation for the SDK
195
+ *
196
+ * Provides a lightweight event system without external dependencies.
197
+ * Supports typed events for better developer experience.
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * interface MyEvents {
202
+ * data: [value: string];
203
+ * error: [error: Error];
204
+ * ready: [];
205
+ * }
206
+ *
207
+ * class MyClass extends EventEmitter<MyEvents> {
208
+ * doSomething() {
209
+ * this.emit('data', 'hello');
210
+ * this.emit('error', new Error('oops'));
211
+ * this.emit('ready');
212
+ * }
213
+ * }
214
+ * ```
215
+ */
216
+ declare class EventEmitter<T extends Record<string, unknown[]>> {
217
+ private listeners;
218
+ /**
219
+ * Register an event listener
220
+ *
221
+ * @param event - Event name
222
+ * @param handler - Event handler function
223
+ *
224
+ * @example
225
+ * ```typescript
226
+ * emitter.on('data', (value) => {
227
+ * console.log('Received:', value);
228
+ * });
229
+ * ```
230
+ */
231
+ on<K extends keyof T>(event: K, handler: (...args: T[K]) => void): void;
232
+ /**
233
+ * Unregister an event listener
234
+ *
235
+ * @param event - Event name
236
+ * @param handler - Event handler function to remove
237
+ *
238
+ * @example
239
+ * ```typescript
240
+ * const handler = (value) => console.log(value);
241
+ * emitter.on('data', handler);
242
+ * emitter.off('data', handler);
243
+ * ```
244
+ */
245
+ off<K extends keyof T>(event: K, handler: (...args: T[K]) => void): void;
246
+ /**
247
+ * Register a one-time event listener
248
+ *
249
+ * The handler will be automatically removed after the first call.
250
+ *
251
+ * @param event - Event name
252
+ * @param handler - Event handler function
253
+ *
254
+ * @example
255
+ * ```typescript
256
+ * emitter.once('ready', () => {
257
+ * console.log('Ready! This will only fire once');
258
+ * });
259
+ * ```
260
+ */
261
+ once<K extends keyof T>(event: K, handler: (...args: T[K]) => void): void;
262
+ /**
263
+ * Emit an event
264
+ *
265
+ * Calls all registered handlers for the event in the order they were registered.
266
+ *
267
+ * @param event - Event name
268
+ * @param args - Arguments to pass to event handlers
269
+ *
270
+ * @example
271
+ * ```typescript
272
+ * emitter.emit('data', 'hello world');
273
+ * emitter.emit('error', new Error('Something went wrong'));
274
+ * ```
275
+ */
276
+ emit<K extends keyof T>(event: K, ...args: T[K]): void;
277
+ /**
278
+ * Remove all listeners for an event or all events
279
+ *
280
+ * @param event - Event name (optional). If not provided, removes all listeners.
281
+ *
282
+ * @example
283
+ * ```typescript
284
+ * // Remove all listeners for 'data' event
285
+ * emitter.removeAllListeners('data');
286
+ *
287
+ * // Remove all listeners for all events
288
+ * emitter.removeAllListeners();
289
+ * ```
290
+ */
291
+ removeAllListeners(event?: keyof T): void;
292
+ /**
293
+ * Get the number of listeners for an event
294
+ *
295
+ * @param event - Event name
296
+ * @returns Number of registered listeners
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * const count = emitter.listenerCount('data');
301
+ * console.log(`There are ${count} data listeners`);
302
+ * ```
303
+ */
304
+ listenerCount(event: keyof T): number;
305
+ /**
306
+ * Get all event names that have listeners
307
+ *
308
+ * @returns Array of event names
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * const events = emitter.eventNames();
313
+ * console.log('Active events:', events);
314
+ * ```
315
+ */
316
+ eventNames(): (keyof T)[];
317
+ }
318
+
319
+ /**
320
+ * Authentication type definitions for Angany Voice SDK
321
+ */
322
+ /**
323
+ * Base authentication options
324
+ */
325
+ interface AuthOptions {
326
+ /**
327
+ * Authentication method
328
+ */
329
+ method: 'frontend' | 'backend' | 'service-account';
330
+ /**
331
+ * Token refresh buffer in seconds
332
+ * @default 300 (5 minutes)
333
+ */
334
+ refreshBufferSeconds?: number;
335
+ /**
336
+ * Enable automatic token refresh
337
+ * @default true
338
+ */
339
+ autoRefresh?: boolean;
340
+ }
341
+ /**
342
+ * Frontend authentication options
343
+ */
344
+ interface FrontendAuthOptions extends AuthOptions {
345
+ method: 'frontend';
346
+ /**
347
+ * OAuth redirect URI
348
+ * If not provided, will use popup flow (not supported by all providers)
349
+ */
350
+ redirectUri?: string;
351
+ /**
352
+ * OAuth scopes to request
353
+ * @default ['openid', 'profile', 'offline_access']
354
+ */
355
+ scopes?: string[];
356
+ /**
357
+ * Storage preference for credentials
358
+ * @default 'localStorage'
359
+ */
360
+ storage?: 'localStorage' | 'sessionStorage' | 'memory';
361
+ }
362
+ /**
363
+ * Backend authentication options
364
+ */
365
+ interface BackendAuthOptions extends AuthOptions {
366
+ method: 'backend';
367
+ redirectUri?: string;
368
+ postLogoutRedirectUris?: string[];
369
+ branding?: BrandingOptions;
370
+ scopes?: string[];
371
+ autoRefresh?: boolean;
372
+ refreshBufferSeconds?: number;
373
+ }
374
+ /**
375
+ * Service account authentication options
376
+ */
377
+ interface ServiceAccountAuthOptions extends AuthOptions {
378
+ method: 'service-account';
379
+ /**
380
+ * Service account credentials
381
+ */
382
+ credentials: ServiceAccountCredentials;
383
+ /**
384
+ * OAuth scopes to request
385
+ * @default ['api:voice', 'api:conversation']
386
+ */
387
+ scopes?: string[];
388
+ }
389
+ /**
390
+ * Service account credentials
391
+ */
392
+ interface ServiceAccountCredentials {
393
+ /**
394
+ * Service account ID
395
+ */
396
+ clientId: string;
397
+ /**
398
+ * Service account secret
399
+ */
400
+ clientSecret: string;
401
+ /**
402
+ * Optional key ID
403
+ */
404
+ keyId?: string;
405
+ /**
406
+ * Optional private key for JWT assertion
407
+ */
408
+ privateKey?: string;
409
+ }
410
+ /**
411
+ * OAuth client credentials (for dynamic registration)
412
+ */
413
+ interface ClientCredentials {
414
+ /**
415
+ * Client ID
416
+ */
417
+ clientId: string;
418
+ /**
419
+ * Client secret (if applicable)
420
+ */
421
+ clientSecret?: string;
422
+ /**
423
+ * Registration access token
424
+ */
425
+ registrationAccessToken?: string;
426
+ /**
427
+ * Registration client URI
428
+ */
429
+ registrationClientUri?: string;
430
+ /**
431
+ * When the credentials were created
432
+ */
433
+ createdAt: Date;
434
+ /**
435
+ * When the credentials expire (if applicable)
436
+ */
437
+ expiresAt?: Date;
438
+ /**
439
+ * Token endpoint authentication method
440
+ */
441
+ tokenEndpointAuthMethod?: string;
442
+ }
443
+ /**
444
+ * Token set
445
+ */
446
+ interface TokenSet {
447
+ /**
448
+ * Access token
449
+ */
450
+ accessToken: string;
451
+ /**
452
+ * Refresh token (if available)
453
+ */
454
+ refreshToken?: string;
455
+ /**
456
+ * ID token (if available)
457
+ */
458
+ idToken?: string;
459
+ /**
460
+ * Token type
461
+ * @default 'Bearer'
462
+ */
463
+ tokenType: string;
464
+ /**
465
+ * Token expiration time (seconds from now)
466
+ */
467
+ expiresIn?: number;
468
+ /**
469
+ * Absolute expiration timestamp
470
+ */
471
+ expiresAt?: Date;
472
+ /**
473
+ * Granted scopes
474
+ */
475
+ scope?: string;
476
+ }
477
+ /**
478
+ * Authentication status
479
+ */
480
+ interface AuthStatus {
481
+ /**
482
+ * Whether the user is authenticated
483
+ */
484
+ authenticated: boolean;
485
+ /**
486
+ * Current authentication method
487
+ */
488
+ method?: 'frontend' | 'backend' | 'service-account';
489
+ /**
490
+ * Current token set
491
+ */
492
+ tokens?: TokenSet;
493
+ /**
494
+ * User information
495
+ */
496
+ user?: UserInfo;
497
+ /**
498
+ * Authentication error (if any)
499
+ */
500
+ error?: AuthError;
501
+ /**
502
+ * Authentication state
503
+ */
504
+ state: AuthState;
505
+ /**
506
+ * When the auth status was last updated
507
+ */
508
+ updatedAt: Date;
509
+ /**
510
+ * OAuth client credentials
511
+ */
512
+ clientCredentials?: ClientCredentials;
513
+ /**
514
+ * When tokens expire
515
+ */
516
+ expiresAt?: Date;
517
+ /**
518
+ * When tokens will be refreshed (if auto-refresh is enabled)
519
+ */
520
+ refreshAt?: Date;
521
+ }
522
+ /**
523
+ * Authentication state
524
+ */
525
+ type AuthState = 'unauthenticated' | 'authenticating' | 'authenticated' | 'refreshing' | 'error';
526
+ /**
527
+ * User information
528
+ */
529
+ interface UserInfo {
530
+ /**
531
+ * User ID
532
+ */
533
+ id: string;
534
+ /**
535
+ * Username
536
+ */
537
+ username?: string;
538
+ /**
539
+ * Email address
540
+ */
541
+ email?: string;
542
+ /**
543
+ * Display name
544
+ */
545
+ name?: string;
546
+ /**
547
+ * User avatar URL
548
+ */
549
+ picture?: string;
550
+ /**
551
+ * User roles
552
+ */
553
+ roles?: string[];
554
+ /**
555
+ * User permissions
556
+ */
557
+ permissions?: string[];
558
+ /**
559
+ * Additional user attributes
560
+ */
561
+ attributes?: Record<string, unknown>;
562
+ }
563
+ /**
564
+ * Authentication error
565
+ */
566
+ interface AuthError {
567
+ /**
568
+ * Error code
569
+ */
570
+ code: string;
571
+ /**
572
+ * Error message
573
+ */
574
+ message: string;
575
+ /**
576
+ * Error details
577
+ */
578
+ details?: Record<string, unknown>;
579
+ /**
580
+ * When the error occurred
581
+ */
582
+ timestamp: Date;
583
+ }
584
+ /**
585
+ * Credential rotation callback
586
+ */
587
+ type CredentialRotationCallback = () => Promise<{
588
+ sip: {
589
+ username: string;
590
+ password: string;
591
+ realm?: string;
592
+ websocketUrl?: string;
593
+ uris?: string[];
594
+ };
595
+ apiToken?: string;
596
+ expiresAt: Date | string;
597
+ expiresIn: number;
598
+ }>;
599
+ /**
600
+ * Authentication event types
601
+ */
602
+ interface AuthEvents extends Record<string, unknown[]> {
603
+ /**
604
+ * Emitted when authentication state changes
605
+ */
606
+ stateChange: [state: AuthState, previousState: AuthState];
607
+ /**
608
+ * Emitted when tokens are refreshed
609
+ */
610
+ tokenRefresh: [tokens: TokenSet];
611
+ /**
612
+ * Emitted when authentication fails
613
+ */
614
+ error: [error: AuthError];
615
+ /**
616
+ * Emitted when user logs out
617
+ */
618
+ logout: [];
619
+ /**
620
+ * Emitted when tokens are about to expire
621
+ */
622
+ tokenExpiring: [expiresIn: number];
623
+ /**
624
+ * Emitted when ephemeral credentials are about to expire
625
+ */
626
+ credentialsExpiring: [expiresIn: number];
627
+ /**
628
+ * Emitted when ephemeral credentials have been refreshed
629
+ */
630
+ credentialsRefreshed: [
631
+ credentials: {
632
+ sip: {
633
+ username: string;
634
+ password: string;
635
+ realm?: string;
636
+ websocketUrl?: string;
637
+ uris?: string[];
638
+ };
639
+ apiToken?: string;
640
+ expiresAt: Date;
641
+ expiresIn: number;
642
+ }
643
+ ];
644
+ /**
645
+ * Emitted when credential rotation fails
646
+ */
647
+ credentialRotationFailed: [error: Error];
648
+ }
649
+ /**
650
+ * Application branding options for OAuth consent page
651
+ */
652
+ interface BrandingOptions {
653
+ /**
654
+ * Application name
655
+ */
656
+ applicationName?: string;
657
+ /**
658
+ * URL to application icon (recommended: 512x512px)
659
+ */
660
+ applicationIcon?: string;
661
+ /**
662
+ * Brief description of your application
663
+ */
664
+ applicationDescription?: string;
665
+ /**
666
+ * Application homepage URL
667
+ */
668
+ homepageUrl?: string;
669
+ /**
670
+ * Terms of service URL
671
+ */
672
+ termsUrl?: string;
673
+ /**
674
+ * Privacy policy URL
675
+ */
676
+ privacyUrl?: string;
677
+ }
678
+
679
+ /**
680
+ * Credential manager for the Angany Voice SDK
681
+ *
682
+ * Handles client credentials registration and ephemeral credentials for WebRTC connections.
683
+ */
684
+
685
+ interface EphemeralCredentials {
686
+ sip: {
687
+ username: string;
688
+ password: string;
689
+ realm?: string;
690
+ websocketUrl?: string;
691
+ uris?: string[];
692
+ };
693
+ apiToken?: string | undefined;
694
+ expiresAt: Date;
695
+ expiresIn: number;
696
+ ice_servers?: RTCIceServer[];
697
+ }
698
+
699
+ /**
700
+ * Authentication manager for the Angany Voice SDK
701
+ *
702
+ * Handles OAuth2 authentication flows, token management, and ephemeral credentials
703
+ * for WebRTC connections. Uses the certified openid-client library for all OAuth2/OIDC operations.
704
+ *
705
+ * Supports multiple authentication patterns:
706
+ * - Frontend (SPA) authentication with redirect or popup
707
+ * - Backend authentication with dynamic client registration
708
+ * - Service account authentication
709
+ *
710
+ * This class acts as a facade over specialized authentication components following SOLID principles.
711
+ */
712
+
713
+ /**
714
+ * Manages authentication for the Angany Voice SDK using openid-client
715
+ *
716
+ * @example Frontend Authentication
717
+ * ```typescript
718
+ * const auth = new AuthManager('https://api.angany.ai');
719
+ * await auth.authenticateFrontend({
720
+ * redirectUri: 'https://app.example.com/callback'
721
+ * });
722
+ * ```
723
+ *
724
+ * @example Backend Authentication with Dynamic Registration
725
+ * ```typescript
726
+ * const auth = new AuthManager('https://api.angany.ai');
727
+ * const result = await auth.authenticateBackend({
728
+ * branding: {
729
+ * applicationName: 'My App',
730
+ * applicationIcon: 'https://example.com/icon.png'
731
+ * }
732
+ * });
733
+ * // Save result.clientCredentials for reuse
734
+ * ```
735
+ */
736
+ declare class AuthManager extends EventEmitter<AuthEvents> {
737
+ private readonly logger;
738
+ private state;
739
+ private options;
740
+ private readonly issuer;
741
+ private readonly storageManager;
742
+ private readonly tokenManager;
743
+ private readonly credentialManager;
744
+ private readonly oauthClient;
745
+ private credentialRotationCallback?;
746
+ private credentialRotationTimeout?;
747
+ private credentialExpiryWarningThreshold;
748
+ constructor(apiUrl: string, issuer?: string);
749
+ /**
750
+ * Try to restore a previous session from localStorage
751
+ * This should be called on app startup to restore authentication state
752
+ *
753
+ * @returns true if session was restored successfully, false otherwise
754
+ *
755
+ * @example
756
+ * ```typescript
757
+ * const auth = new AuthManager('https://api.angany.ai');
758
+ * const restored = await auth.tryRestoreSession();
759
+ * if (restored) {
760
+ * console.log('Session restored, user is authenticated');
761
+ * } else {
762
+ * console.log('No session to restore, redirect to login');
763
+ * }
764
+ * ```
765
+ */
766
+ tryRestoreSession(): Promise<boolean>;
767
+ /**
768
+ * Authenticate using frontend flow (SPA)
769
+ */
770
+ authenticateFrontend(options?: Partial<FrontendAuthOptions>): Promise<void>;
771
+ /**
772
+ * Authenticate using backend flow
773
+ */
774
+ authenticateBackend(options?: Partial<BackendAuthOptions>): Promise<{
775
+ clientCredentials: ClientCredentials;
776
+ authUrl?: string;
777
+ }>;
778
+ /**
779
+ * Authenticate using service account (client credentials)
780
+ */
781
+ authenticateServiceAccount(options: ServiceAccountAuthOptions): Promise<void>;
782
+ /**
783
+ * Use existing client credentials
784
+ */
785
+ useExistingCredentials(credentials: ClientCredentials, options?: {
786
+ redirectUri?: string;
787
+ scope?: string;
788
+ }): Promise<void>;
789
+ /**
790
+ * Get authorization URL for OAuth flow
791
+ */
792
+ getAuthorizationUrl(): Promise<{
793
+ url: string;
794
+ codeVerifier: string;
795
+ state: string;
796
+ }>;
797
+ /**
798
+ * Set PKCE code verifier (for backend flows)
799
+ */
800
+ setCodeVerifier(codeVerifier: string): void;
801
+ /**
802
+ * Handle OAuth callback
803
+ */
804
+ handleCallback(code: string, state: string, codeVerifier?: string): Promise<{
805
+ success: boolean;
806
+ user?: UserInfo;
807
+ }>;
808
+ /**
809
+ * Check if ephemeral credentials are available and valid
810
+ */
811
+ hasValidEphemeralCredentials(): boolean;
812
+ /**
813
+ * Get cached ephemeral credentials (if valid)
814
+ */
815
+ getCachedEphemeralCredentials(): EphemeralCredentials | undefined;
816
+ /**
817
+ * Get current authentication status
818
+ */
819
+ getAuthStatus(): AuthStatus;
820
+ /**
821
+ * Get current tokens
822
+ */
823
+ getTokens(): TokenSet | undefined;
824
+ /**
825
+ * Get access token
826
+ */
827
+ getAccessToken(): Promise<string | undefined>;
828
+ /**
829
+ * Refresh tokens
830
+ */
831
+ refreshTokens(): Promise<TokenSet>;
832
+ /**
833
+ * Set ephemeral credentials for WebRTC connections
834
+ */
835
+ setEphemeralCredentials(credentials: {
836
+ sip: {
837
+ username: string;
838
+ password: string;
839
+ realm?: string;
840
+ websocketUrl?: string;
841
+ uris?: string[];
842
+ };
843
+ apiToken?: string;
844
+ expiresAt: Date | string;
845
+ expiresIn: number;
846
+ }): void;
847
+ /**
848
+ * Set OAuth access token for API calls (hybrid approach)
849
+ */
850
+ setOAuthAccessToken(accessToken: string): void;
851
+ /**
852
+ * Get ephemeral credentials for a specific user (admin function)
853
+ */
854
+ getEphemeralCredentialsForUser(userAccessToken: string): Promise<EphemeralCredentials>;
855
+ /**
856
+ * Get ephemeral credentials for WebRTC connections
857
+ */
858
+ getEphemeralCredentials(): Promise<EphemeralCredentials>;
859
+ /**
860
+ * Renew ephemeral credentials
861
+ */
862
+ renewEphemeralCredentials(): Promise<void>;
863
+ /**
864
+ * Set credential rotation callback
865
+ * This callback will be called when credentials are about to expire
866
+ */
867
+ setCredentialRotationCallback(callback: CredentialRotationCallback): void;
868
+ /**
869
+ * Clear credential rotation callback
870
+ */
871
+ clearCredentialRotationCallback(): void;
872
+ /**
873
+ * Set credential expiry warning threshold (in seconds before expiry)
874
+ */
875
+ setCredentialExpiryWarningThreshold(seconds: number): void;
876
+ /**
877
+ * Schedule credential rotation based on actual expiry time
878
+ */
879
+ private scheduleCredentialRotation;
880
+ /**
881
+ * Clear credential rotation timeout
882
+ */
883
+ private clearCredentialRotationTimeout;
884
+ /**
885
+ * Perform credential rotation
886
+ */
887
+ private performCredentialRotation;
888
+ /**
889
+ * Logout user
890
+ */
891
+ logout(options?: {
892
+ clearStoredClient?: boolean;
893
+ redirectToProvider?: boolean;
894
+ postLogoutRedirectUri?: string;
895
+ }): Promise<string | void>;
896
+ /**
897
+ * Initialize backend authentication (legacy method)
898
+ */
899
+ initializeBackend(options: BackendAuthOptions & {
900
+ redirectUri?: string;
901
+ scope?: string;
902
+ }): Promise<{
903
+ clientId?: string;
904
+ }>;
905
+ /**
906
+ * Restore tokens from external source
907
+ */
908
+ restoreTokens(tokens: TokenSet): void;
909
+ /**
910
+ * Set authentication state
911
+ */
912
+ private setState;
913
+ }
914
+
915
+ /**
916
+ * Conversation type definitions for Angany Voice SDK
917
+ */
918
+
919
+ /**
920
+ * Conversation options
921
+ */
922
+ interface ConversationOptions {
923
+ /**
924
+ * Voice resource ID or name
925
+ */
926
+ resource: string;
927
+ /**
928
+ * Conversation metadata
929
+ */
930
+ metadata?: Record<string, unknown>;
931
+ /**
932
+ * Audio configuration
933
+ */
934
+ audio?: AudioConfig;
935
+ /**
936
+ * Enable automatic reconnection
937
+ * @default true
938
+ */
939
+ autoReconnect?: boolean;
940
+ /**
941
+ * Maximum reconnection attempts
942
+ * @default 5
943
+ */
944
+ maxReconnectAttempts?: number;
945
+ /**
946
+ * Reconnection delay in milliseconds
947
+ * @default 1000
948
+ */
949
+ reconnectDelay?: number;
950
+ /**
951
+ * Enable echo cancellation
952
+ * @default true
953
+ */
954
+ echoCancellation?: boolean;
955
+ /**
956
+ * Enable noise suppression
957
+ * @default true
958
+ */
959
+ noiseSuppression?: boolean;
960
+ /**
961
+ * Enable automatic gain control
962
+ * @default true
963
+ */
964
+ autoGainControl?: boolean;
965
+ /**
966
+ * Custom SIP headers
967
+ */
968
+ sipHeaders?: Record<string, string>;
969
+ /**
970
+ * Conversation timeout in milliseconds
971
+ * @default 3600000 (1 hour)
972
+ */
973
+ timeout?: number;
974
+ }
975
+ /**
976
+ * Audio configuration
977
+ */
978
+ interface AudioConfig {
979
+ /**
980
+ * Input device ID
981
+ */
982
+ inputDeviceId?: string;
983
+ /**
984
+ * Output device ID
985
+ */
986
+ outputDeviceId?: string;
987
+ /**
988
+ * Sample rate
989
+ * @default 48000
990
+ */
991
+ sampleRate?: number;
992
+ /**
993
+ * Audio codec preferences
994
+ */
995
+ codecs?: AudioCodec[];
996
+ /**
997
+ * Enable stereo
998
+ * @default false
999
+ */
1000
+ stereo?: boolean;
1001
+ /**
1002
+ * Audio constraints
1003
+ */
1004
+ constraints?: MediaTrackConstraints;
1005
+ }
1006
+ /**
1007
+ * Audio codec
1008
+ */
1009
+ type AudioCodec = 'opus' | 'PCMU' | 'PCMA' | 'G722' | 'iLBC' | 'VP8';
1010
+ /**
1011
+ * Conversation state
1012
+ */
1013
+ type ConversationState = 'idle' | 'connecting' | 'connected' | 'active' | 'held' | 'muted' | 'disconnecting' | 'disconnected' | 'failed' | 'reconnecting' | 'error';
1014
+ /**
1015
+ * Conversation status
1016
+ */
1017
+ interface ConversationStatus {
1018
+ /**
1019
+ * Current state
1020
+ */
1021
+ state: ConversationState;
1022
+ /**
1023
+ * Conversation ID
1024
+ */
1025
+ id?: string;
1026
+ /**
1027
+ * SIP call ID
1028
+ */
1029
+ callId?: string;
1030
+ /**
1031
+ * Resource information
1032
+ */
1033
+ resource?: VoiceResource;
1034
+ /**
1035
+ * Start time
1036
+ */
1037
+ startTime?: Date;
1038
+ /**
1039
+ * End time
1040
+ */
1041
+ endTime?: Date;
1042
+ /**
1043
+ * Duration in seconds
1044
+ */
1045
+ duration?: number;
1046
+ /**
1047
+ * Whether the agent is muted
1048
+ */
1049
+ agentMuted: boolean;
1050
+ /**
1051
+ * Whether the user is muted
1052
+ */
1053
+ userMuted: boolean;
1054
+ /**
1055
+ * Connection quality
1056
+ */
1057
+ quality?: ConnectionQuality;
1058
+ /**
1059
+ * Error information
1060
+ */
1061
+ error?: ConversationError$1;
1062
+ /**
1063
+ * Conversation metadata
1064
+ */
1065
+ metadata?: Record<string, unknown>;
1066
+ }
1067
+ /**
1068
+ * Connection quality
1069
+ */
1070
+ interface ConnectionQuality {
1071
+ /**
1072
+ * Overall quality score (0-100)
1073
+ */
1074
+ score: number;
1075
+ /**
1076
+ * Quality level
1077
+ */
1078
+ level: 'excellent' | 'good' | 'fair' | 'poor';
1079
+ /**
1080
+ * Network statistics
1081
+ */
1082
+ stats?: NetworkStats;
1083
+ }
1084
+ /**
1085
+ * Network statistics
1086
+ */
1087
+ interface NetworkStats {
1088
+ /**
1089
+ * Round-trip time in milliseconds
1090
+ */
1091
+ rtt?: number;
1092
+ /**
1093
+ * Packet loss percentage
1094
+ */
1095
+ packetLoss?: number;
1096
+ /**
1097
+ * Jitter in milliseconds
1098
+ */
1099
+ jitter?: number;
1100
+ /**
1101
+ * Bandwidth usage in kbps
1102
+ */
1103
+ bandwidth?: {
1104
+ upload?: number;
1105
+ download?: number;
1106
+ };
1107
+ }
1108
+ /**
1109
+ * Transcription event
1110
+ */
1111
+ interface TranscriptionEvent {
1112
+ /**
1113
+ * Event ID
1114
+ */
1115
+ id: string;
1116
+ /**
1117
+ * Event type
1118
+ */
1119
+ type: 'partial' | 'final';
1120
+ /**
1121
+ * Speaker role
1122
+ */
1123
+ role: 'user' | 'agent';
1124
+ /**
1125
+ * Transcribed text
1126
+ */
1127
+ text: string;
1128
+ /**
1129
+ * Timestamp
1130
+ */
1131
+ timestamp: Date;
1132
+ /**
1133
+ * Duration in seconds
1134
+ */
1135
+ duration?: number;
1136
+ /**
1137
+ * Confidence score (0-1)
1138
+ */
1139
+ confidence?: number;
1140
+ /**
1141
+ * Language code
1142
+ */
1143
+ language?: string;
1144
+ /**
1145
+ * Alternative transcriptions
1146
+ */
1147
+ alternatives?: TranscriptionAlternative[];
1148
+ /**
1149
+ * Additional metadata
1150
+ */
1151
+ metadata?: Record<string, unknown>;
1152
+ }
1153
+ /**
1154
+ * Transcription alternative
1155
+ */
1156
+ interface TranscriptionAlternative {
1157
+ /**
1158
+ * Alternative text
1159
+ */
1160
+ text: string;
1161
+ /**
1162
+ * Confidence score (0-1)
1163
+ */
1164
+ confidence: number;
1165
+ }
1166
+ /**
1167
+ * Speak options
1168
+ */
1169
+ interface SpeakOptions {
1170
+ /**
1171
+ * Whether to interrupt current speech
1172
+ * @default false
1173
+ */
1174
+ interrupt?: boolean;
1175
+ /**
1176
+ * Priority level
1177
+ * @default 'normal'
1178
+ */
1179
+ priority?: 'low' | 'normal' | 'high' | 'urgent';
1180
+ /**
1181
+ * Callback when speech starts
1182
+ */
1183
+ onStart?: () => void;
1184
+ /**
1185
+ * Callback when speech ends
1186
+ */
1187
+ onEnd?: () => void;
1188
+ /**
1189
+ * Callback on error
1190
+ */
1191
+ onError?: (error: Error) => void;
1192
+ /**
1193
+ * Custom metadata
1194
+ */
1195
+ metadata?: Record<string, unknown>;
1196
+ }
1197
+ /**
1198
+ * Conversation error
1199
+ */
1200
+ interface ConversationError$1 {
1201
+ /**
1202
+ * Error code
1203
+ */
1204
+ code: string;
1205
+ /**
1206
+ * Error message
1207
+ */
1208
+ message: string;
1209
+ /**
1210
+ * Error type
1211
+ */
1212
+ type: 'network' | 'permission' | 'resource' | 'timeout' | 'unknown';
1213
+ /**
1214
+ * Whether the error is recoverable
1215
+ */
1216
+ recoverable: boolean;
1217
+ /**
1218
+ * Error details
1219
+ */
1220
+ details?: Record<string, unknown>;
1221
+ /**
1222
+ * Original error
1223
+ */
1224
+ cause?: Error;
1225
+ }
1226
+ /**
1227
+ * Conversation events
1228
+ */
1229
+ interface ConversationEvents extends Record<string, unknown[]> {
1230
+ /**
1231
+ * Emitted when state changes
1232
+ */
1233
+ stateChange: [state: ConversationState, previousState: ConversationState];
1234
+ /**
1235
+ * Emitted when connected
1236
+ */
1237
+ connected: [];
1238
+ /**
1239
+ * Emitted when disconnected
1240
+ */
1241
+ disconnected: [reason?: string];
1242
+ /**
1243
+ * Emitted on transcription
1244
+ */
1245
+ transcription: [
1246
+ event: {
1247
+ speaker: 'user' | 'agent';
1248
+ text: string;
1249
+ timestamp: Date;
1250
+ isFinal: boolean;
1251
+ }
1252
+ ];
1253
+ /**
1254
+ * Emitted on error
1255
+ */
1256
+ error: [error: Error];
1257
+ /**
1258
+ * Emitted when agent is muted/unmuted
1259
+ */
1260
+ agentMuted: [muted: boolean];
1261
+ /**
1262
+ * Emitted when user is muted/unmuted
1263
+ */
1264
+ userMuted: [muted: boolean];
1265
+ /**
1266
+ * Emitted when connection quality changes
1267
+ */
1268
+ qualityChange: [quality: ConnectionQuality];
1269
+ /**
1270
+ * Emitted when reconnecting
1271
+ */
1272
+ reconnecting: [attempt: number];
1273
+ /**
1274
+ * Emitted when reconnected
1275
+ */
1276
+ reconnected: [];
1277
+ /**
1278
+ * Emitted when conversation ends
1279
+ */
1280
+ ended: [summary: {
1281
+ duration: number;
1282
+ }];
1283
+ /**
1284
+ * Emitted with audio level updates
1285
+ */
1286
+ audioLevel: [level: number];
1287
+ }
1288
+
1289
+ /**
1290
+ * Conversation management
1291
+ */
1292
+
1293
+ /**
1294
+ * Represents an active voice conversation
1295
+ */
1296
+ declare class Conversation extends EventEmitter<ConversationEvents> {
1297
+ private logger;
1298
+ private id;
1299
+ private state;
1300
+ private options;
1301
+ private agentMuted;
1302
+ private userMuted;
1303
+ private startTime?;
1304
+ private endTime?;
1305
+ private apiUrl;
1306
+ private authManager;
1307
+ private sipManager;
1308
+ private transcriptionService;
1309
+ private apiService;
1310
+ private callId?;
1311
+ private ephemeralCredentials?;
1312
+ private accessToken?;
1313
+ constructor(id: string, options: ConversationOptions, authManager: AuthManager, apiUrl: string);
1314
+ /**
1315
+ * Initialize and start the conversation
1316
+ */
1317
+ initialize(): Promise<void>;
1318
+ /**
1319
+ * Send text to be spoken in the conversation
1320
+ */
1321
+ speak(text: string, options?: {
1322
+ interrupt?: boolean;
1323
+ waitForResponse?: boolean;
1324
+ }): Promise<void>;
1325
+ /**
1326
+ * Mute or unmute the user's microphone
1327
+ */
1328
+ mute(muted: boolean): void;
1329
+ /**
1330
+ * Mute the agent
1331
+ */
1332
+ muteAgent(muted?: boolean): Promise<void>;
1333
+ /**
1334
+ * Unmute the agent (convenience method)
1335
+ */
1336
+ unmuteAgent(): Promise<void>;
1337
+ /**
1338
+ * Check if agent is muted
1339
+ */
1340
+ isAgentMuted(): boolean;
1341
+ /**
1342
+ * Get conversation status
1343
+ */
1344
+ getStatus(): Promise<ConversationStatus>;
1345
+ /**
1346
+ * End the conversation
1347
+ */
1348
+ end(): Promise<void>;
1349
+ /**
1350
+ * Get the conversation ID
1351
+ */
1352
+ getId(): string;
1353
+ /**
1354
+ * Get the current state
1355
+ */
1356
+ getState(): ConversationState;
1357
+ /**
1358
+ * Get the resource ID
1359
+ */
1360
+ get resourceId(): string;
1361
+ /**
1362
+ * Get the conversation status (for compatibility)
1363
+ */
1364
+ get status(): string;
1365
+ /**
1366
+ * Enable audio playback (call after user interaction to bypass autoplay restrictions)
1367
+ */
1368
+ enableAudio(): Promise<void>;
1369
+ /**
1370
+ * Check if audio is playing
1371
+ */
1372
+ isAudioPlaying(): boolean;
1373
+ /**
1374
+ * Set audio volume (0.0 to 1.0)
1375
+ */
1376
+ setVolume(volume: number): void;
1377
+ /**
1378
+ * Mute or unmute the remote audio
1379
+ */
1380
+ setAudioMuted(muted: boolean): void;
1381
+ /**
1382
+ * Get the audio element for external control
1383
+ */
1384
+ getAudioElement(): HTMLAudioElement | undefined;
1385
+ private setState;
1386
+ private setupSipHandlers;
1387
+ private setupTranscriptionHandlers;
1388
+ private cleanup;
1389
+ private extractServerFromUris;
1390
+ }
1391
+
1392
+ /**
1393
+ * Main entry point for the Angany Voice SDK
1394
+ */
1395
+
1396
+ interface VoiceEvents extends Record<string, unknown[]> {
1397
+ /**
1398
+ * Emitted when a conversation is started
1399
+ */
1400
+ conversationStarted: [conversation: Conversation];
1401
+ /**
1402
+ * Emitted when a conversation ends
1403
+ */
1404
+ conversationEnded: [conversationId: string];
1405
+ }
1406
+ /**
1407
+ * Main SDK class for managing voice conversations
1408
+ */
1409
+ declare class AnganyVoice extends EventEmitter<VoiceEvents> {
1410
+ private logger;
1411
+ private config;
1412
+ private conversations;
1413
+ /**
1414
+ * Authentication manager instance
1415
+ */
1416
+ readonly auth: AuthManager;
1417
+ constructor(config: VoiceConfig);
1418
+ /**
1419
+ * Get the current configuration
1420
+ */
1421
+ getConfig(): VoiceConfig;
1422
+ /**
1423
+ * Start a new conversation
1424
+ */
1425
+ startConversation(resourceId: string, options?: Partial<ConversationOptions>): Promise<Conversation>;
1426
+ /**
1427
+ * Get an existing conversation by ID
1428
+ */
1429
+ getConversation(id: string): Conversation | undefined;
1430
+ /**
1431
+ * Get all active conversations
1432
+ */
1433
+ getConversations(): Conversation[];
1434
+ /**
1435
+ * End all conversations and cleanup
1436
+ */
1437
+ cleanup(): Promise<void>;
1438
+ }
1439
+
1440
+ /**
1441
+ * Error classes for the Angany Voice SDK
1442
+ *
1443
+ * Provides a hierarchy of error types for different failure scenarios.
1444
+ * All SDK errors extend from AnganyError for easy error handling.
1445
+ *
1446
+ * @example Catching specific errors
1447
+ * ```typescript
1448
+ * try {
1449
+ * await voice.startConversation('agent');
1450
+ * } catch (error) {
1451
+ * if (error instanceof AuthenticationError) {
1452
+ * // Handle auth failure
1453
+ * } else if (error instanceof NetworkError) {
1454
+ * // Handle network issue
1455
+ * }
1456
+ * }
1457
+ * ```
1458
+ */
1459
+ /**
1460
+ * Base error class for all SDK errors
1461
+ *
1462
+ * All SDK-specific errors extend from this class, making it easy
1463
+ * to catch any SDK error with a single catch block.
1464
+ *
1465
+ * @example
1466
+ * ```typescript
1467
+ * try {
1468
+ * // SDK operations
1469
+ * } catch (error) {
1470
+ * if (error instanceof AnganyError) {
1471
+ * console.log('SDK error:', error.code, error.message);
1472
+ * }
1473
+ * }
1474
+ * ```
1475
+ */
1476
+ declare class AnganyError extends Error {
1477
+ /**
1478
+ * Machine-readable error code
1479
+ *
1480
+ * Use this for programmatic error handling instead of parsing messages.
1481
+ */
1482
+ readonly code: string;
1483
+ /**
1484
+ * Additional error details
1485
+ *
1486
+ * May contain extra context, original errors, or debugging information.
1487
+ */
1488
+ readonly details?: any;
1489
+ /**
1490
+ * Timestamp when the error occurred
1491
+ */
1492
+ readonly timestamp: Date;
1493
+ constructor(message: string, code: string, details?: any);
1494
+ /**
1495
+ * Get a JSON representation of the error
1496
+ *
1497
+ * Useful for logging or sending error reports.
1498
+ *
1499
+ * @returns JSON-serializable error object
1500
+ */
1501
+ toJSON(): Record<string, any>;
1502
+ }
1503
+ /**
1504
+ * Authentication-related errors
1505
+ *
1506
+ * Thrown when authentication fails or tokens are invalid/expired.
1507
+ *
1508
+ * @example
1509
+ * ```typescript
1510
+ * throw new AuthenticationError('Invalid credentials', {
1511
+ * reason: 'wrong_password'
1512
+ * });
1513
+ * ```
1514
+ */
1515
+ declare class AuthenticationError extends AnganyError {
1516
+ constructor(message: string, details?: any);
1517
+ }
1518
+ /**
1519
+ * Network-related errors
1520
+ *
1521
+ * Thrown when network requests fail or connections are lost.
1522
+ *
1523
+ * @example
1524
+ * ```typescript
1525
+ * throw new NetworkError('Connection timeout', {
1526
+ * url: 'https://api.angany.ai',
1527
+ * timeout: 30000
1528
+ * });
1529
+ * ```
1530
+ */
1531
+ declare class NetworkError extends AnganyError {
1532
+ constructor(message: string, details?: any);
1533
+ }
1534
+ /**
1535
+ * Permission-related errors
1536
+ *
1537
+ * Thrown when required permissions are denied (e.g., microphone access).
1538
+ *
1539
+ * @example
1540
+ * ```typescript
1541
+ * throw new PermissionError('Microphone access denied', {
1542
+ * permission: 'microphone',
1543
+ * state: 'denied'
1544
+ * });
1545
+ * ```
1546
+ */
1547
+ declare class PermissionError extends AnganyError {
1548
+ constructor(message: string, details?: any);
1549
+ }
1550
+ /**
1551
+ * Conversation-related errors
1552
+ *
1553
+ * Thrown when conversation operations fail.
1554
+ *
1555
+ * @example
1556
+ * ```typescript
1557
+ * throw new ConversationError('Failed to start conversation', {
1558
+ * resource: 'support-agent',
1559
+ * reason: 'resource_not_found'
1560
+ * });
1561
+ * ```
1562
+ */
1563
+ declare class ConversationError extends AnganyError {
1564
+ constructor(message: string, details?: any);
1565
+ }
1566
+ /**
1567
+ * Configuration errors
1568
+ *
1569
+ * Thrown when SDK is misconfigured or required options are missing.
1570
+ *
1571
+ * @example
1572
+ * ```typescript
1573
+ * throw new ConfigurationError('Missing required option: apiUrl', {
1574
+ * option: 'apiUrl',
1575
+ * provided: config
1576
+ * });
1577
+ * ```
1578
+ */
1579
+ declare class ConfigurationError extends AnganyError {
1580
+ constructor(message: string, details?: any);
1581
+ }
1582
+ /**
1583
+ * Resource errors
1584
+ *
1585
+ * Thrown when requested resources are not found or unavailable.
1586
+ *
1587
+ * @example
1588
+ * ```typescript
1589
+ * throw new ResourceError('Voice bot not found', {
1590
+ * resource: 'custom-agent',
1591
+ * availableResources: ['support', 'sales']
1592
+ * });
1593
+ * ```
1594
+ */
1595
+ declare class ResourceError extends AnganyError {
1596
+ constructor(message: string, details?: any);
1597
+ }
1598
+ /**
1599
+ * Validation errors
1600
+ *
1601
+ * Thrown when input validation fails.
1602
+ *
1603
+ * @example
1604
+ * ```typescript
1605
+ * throw new ValidationError('Invalid phone number format', {
1606
+ * field: 'phoneNumber',
1607
+ * value: '123',
1608
+ * pattern: /^\+?[1-9]\d{1,14}$/
1609
+ * });
1610
+ * ```
1611
+ */
1612
+ declare class ValidationError extends AnganyError {
1613
+ constructor(message: string, details?: any);
1614
+ }
1615
+ /**
1616
+ * Media errors
1617
+ *
1618
+ * Thrown when audio/video operations fail.
1619
+ *
1620
+ * @example
1621
+ * ```typescript
1622
+ * throw new MediaError('Failed to acquire microphone', {
1623
+ * constraints: { audio: true },
1624
+ * browserError: error
1625
+ * });
1626
+ * ```
1627
+ */
1628
+ declare class MediaError extends AnganyError {
1629
+ constructor(message: string, details?: any);
1630
+ }
1631
+ /**
1632
+ * Common error codes used throughout the SDK
1633
+ *
1634
+ * Use these constants for consistent error handling.
1635
+ *
1636
+ * @example
1637
+ * ```typescript
1638
+ * if (error.code === ErrorCodes.TOKEN_EXPIRED) {
1639
+ * await auth.refreshTokens();
1640
+ * }
1641
+ * ```
1642
+ */
1643
+ declare const ErrorCodes: {
1644
+ readonly AUTH_REQUIRED: "AUTH_REQUIRED";
1645
+ readonly TOKEN_EXPIRED: "TOKEN_EXPIRED";
1646
+ readonly TOKEN_INVALID: "TOKEN_INVALID";
1647
+ readonly REFRESH_FAILED: "REFRESH_FAILED";
1648
+ readonly LOGIN_REQUIRED: "LOGIN_REQUIRED";
1649
+ readonly UNAUTHORIZED: "UNAUTHORIZED";
1650
+ readonly NETWORK_ERROR: "NETWORK_ERROR";
1651
+ readonly CONNECTION_LOST: "CONNECTION_LOST";
1652
+ readonly TIMEOUT: "TIMEOUT";
1653
+ readonly SERVER_ERROR: "SERVER_ERROR";
1654
+ readonly RESOURCE_NOT_FOUND: "RESOURCE_NOT_FOUND";
1655
+ readonly RESOURCE_UNAVAILABLE: "RESOURCE_UNAVAILABLE";
1656
+ readonly QUOTA_EXCEEDED: "QUOTA_EXCEEDED";
1657
+ readonly MICROPHONE_DENIED: "MICROPHONE_DENIED";
1658
+ readonly MICROPHONE_NOT_FOUND: "MICROPHONE_NOT_FOUND";
1659
+ readonly MEDIA_ERROR: "MEDIA_ERROR";
1660
+ readonly SIP_REGISTRATION_FAILED: "SIP_REGISTRATION_FAILED";
1661
+ readonly CALL_FAILED: "CALL_FAILED";
1662
+ readonly CONVERSATION_ENDED: "CONVERSATION_ENDED";
1663
+ readonly INVALID_CONFIG: "INVALID_CONFIG";
1664
+ readonly MISSING_REQUIRED_OPTION: "MISSING_REQUIRED_OPTION";
1665
+ readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
1666
+ readonly NOT_IMPLEMENTED: "NOT_IMPLEMENTED";
1667
+ };
1668
+ /**
1669
+ * Helper function to check if an error is an SDK error
1670
+ *
1671
+ * @param error - Error to check
1672
+ * @returns True if the error is an AnganyError
1673
+ *
1674
+ * @example
1675
+ * ```typescript
1676
+ * try {
1677
+ * // SDK operation
1678
+ * } catch (error) {
1679
+ * if (isAnganyError(error)) {
1680
+ * console.log('SDK error code:', error.code);
1681
+ * }
1682
+ * }
1683
+ * ```
1684
+ */
1685
+ declare function isAnganyError(error: unknown): error is AnganyError;
1686
+ /**
1687
+ * Helper function to check if an error is a specific type
1688
+ *
1689
+ * @param error - Error to check
1690
+ * @param code - Error code to match
1691
+ * @returns True if the error has the specified code
1692
+ *
1693
+ * @example
1694
+ * ```typescript
1695
+ * if (hasErrorCode(error, ErrorCodes.TOKEN_EXPIRED)) {
1696
+ * // Handle token expiration
1697
+ * }
1698
+ * ```
1699
+ */
1700
+ declare function hasErrorCode(error: unknown, code: string): boolean;
1701
+
1702
+ /**
1703
+ * SDK version
1704
+ * This is automatically updated during the release process
1705
+ */
1706
+ declare const VERSION = "0.0.1";
1707
+
1708
+ export { AnganyError, AnganyVoice, type AuthError, type AuthEvents, AuthManager, type AuthOptions, type AuthState, type AuthStatus, AuthenticationError, type BackendAuthOptions, type ClientCredentials, ConfigurationError, Conversation, ConversationError, type ConversationOptions, type ConversationState, type ConversationStatus, ErrorCodes, EventEmitter, type FrontendAuthOptions, type LogLevel, MediaError, NetworkError, PermissionError, ResourceError, type ServiceAccountAuthOptions, type ServiceAccountCredentials, type SpeakOptions, type TokenSet, type TranscriptionEvent, type UserInfo, VERSION, ValidationError, type VoiceConfig, type VoiceResource, hasErrorCode, isAnganyError };