@anganyai/voice-sdk 0.0.6 → 0.0.8

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/dist/index.cjs CHANGED
@@ -16423,6 +16423,18 @@ var SipManager = class extends EventEmitter {
16423
16423
  }
16424
16424
  const inviter = new Inviter(this.userAgent, uri, inviterOptions);
16425
16425
  this.currentSession = inviter;
16426
+ let rejectionReason;
16427
+ inviter.delegate = {
16428
+ onReject: (response) => {
16429
+ const statusCode = response.message.statusCode;
16430
+ const reasonPhrase = response.message.reasonPhrase;
16431
+ this.logger.warn("Call rejected", { statusCode, reasonPhrase });
16432
+ rejectionReason = {
16433
+ code: statusCode,
16434
+ reason: this.mapSipErrorToMessage(statusCode, reasonPhrase)
16435
+ };
16436
+ }
16437
+ };
16426
16438
  inviter.stateChange.addListener((state) => {
16427
16439
  this.logger.debug("Call state changed", { state });
16428
16440
  switch (state) {
@@ -16436,6 +16448,9 @@ var SipManager = class extends EventEmitter {
16436
16448
  break;
16437
16449
  case SessionState2.Terminated:
16438
16450
  this.setState("registered");
16451
+ if (rejectionReason) {
16452
+ this.emit("error", new Error(rejectionReason.reason));
16453
+ }
16439
16454
  this.emit("callEnded");
16440
16455
  this.cleanupAudioResources();
16441
16456
  delete this.currentSession;
@@ -16901,6 +16916,50 @@ var SipManager = class extends EventEmitter {
16901
16916
  }
16902
16917
  }, delay);
16903
16918
  }
16919
+ /**
16920
+ * Map SIP error codes to user-friendly messages
16921
+ */
16922
+ mapSipErrorToMessage(statusCode, reasonPhrase) {
16923
+ const errorMessages = {
16924
+ // 4xx Client Errors
16925
+ 400: "Invalid request",
16926
+ 401: "Authentication required",
16927
+ 403: "Access denied",
16928
+ 404: "Agent not found",
16929
+ 408: "Request timeout",
16930
+ 480: "Agent unavailable",
16931
+ 486: "Agent is busy",
16932
+ 487: "Call cancelled",
16933
+ 488: "Not acceptable",
16934
+ // 5xx Server Errors
16935
+ 500: "Server error",
16936
+ 502: "Bad gateway",
16937
+ 503: "Service unavailable",
16938
+ 504: "Gateway timeout",
16939
+ // 6xx Global Failures
16940
+ 600: "Agent is busy",
16941
+ 603: "Agent declined the call",
16942
+ 604: "Agent does not exist",
16943
+ 606: "Not acceptable"
16944
+ };
16945
+ const message = errorMessages[statusCode];
16946
+ if (message) {
16947
+ return message;
16948
+ }
16949
+ if (reasonPhrase) {
16950
+ return reasonPhrase;
16951
+ }
16952
+ if (statusCode >= 400 && statusCode < 500) {
16953
+ return "Call failed";
16954
+ }
16955
+ if (statusCode >= 500 && statusCode < 600) {
16956
+ return "Server error";
16957
+ }
16958
+ if (statusCode >= 600) {
16959
+ return "Agent unavailable";
16960
+ }
16961
+ return "Unknown error";
16962
+ }
16904
16963
  };
16905
16964
 
16906
16965
  // src/services/TranscriptionService.ts
@@ -16912,8 +16971,18 @@ var TranscriptionService = class extends EventEmitter {
16912
16971
  this.maxReconnectAttempts = 5;
16913
16972
  this.reconnectDelay = 1e3;
16914
16973
  this.isIntentionallyClosed = false;
16974
+ this.useEventSource = false;
16915
16975
  this.apiUrl = apiUrl;
16916
16976
  }
16977
+ /**
16978
+ * Set EventSource factory for React Native environments
16979
+ * Call this before start() to use EventSource instead of fetch streams
16980
+ */
16981
+ setEventSourceFactory(factory) {
16982
+ this.eventSourceFactory = factory;
16983
+ this.useEventSource = true;
16984
+ this.logger.debug("EventSource factory set - will use EventSource mode");
16985
+ }
16917
16986
  /**
16918
16987
  * Set token refresh callback for handling expired tokens
16919
16988
  */
@@ -16943,7 +17012,10 @@ var TranscriptionService = class extends EventEmitter {
16943
17012
  */
16944
17013
  async connectToSSE(accessToken, isRetry = false) {
16945
17014
  const sseUrl = `${this.apiUrl}/api/v1/events?event_types=transcription,call_event`;
16946
- this.logger.debug("Connecting to SSE endpoint", { url: sseUrl, isRetry });
17015
+ this.logger.debug("Connecting to SSE endpoint", { url: sseUrl, isRetry, useEventSource: this.useEventSource });
17016
+ if (this.useEventSource && this.eventSourceFactory) {
17017
+ return this.connectWithEventSource(sseUrl, accessToken);
17018
+ }
16947
17019
  const response = await fetch(sseUrl, {
16948
17020
  method: "GET",
16949
17021
  headers: {
@@ -16981,6 +17053,65 @@ var TranscriptionService = class extends EventEmitter {
16981
17053
  this.reader = response.body.getReader();
16982
17054
  this.processStream();
16983
17055
  }
17056
+ /**
17057
+ * Connect using EventSource (for React Native)
17058
+ */
17059
+ connectWithEventSource(sseUrl, accessToken) {
17060
+ if (!this.eventSourceFactory) {
17061
+ throw new Error("EventSource factory not set");
17062
+ }
17063
+ this.logger.debug("Connecting with EventSource", { url: sseUrl });
17064
+ if (this.eventSource) {
17065
+ this.eventSource.removeAllEventListeners();
17066
+ this.eventSource.close();
17067
+ }
17068
+ this.eventSource = this.eventSourceFactory(sseUrl, {
17069
+ headers: {
17070
+ Authorization: `Bearer ${accessToken}`,
17071
+ Accept: "text/event-stream",
17072
+ "Cache-Control": "no-cache"
17073
+ }
17074
+ });
17075
+ this.eventSource.addEventListener("open", () => {
17076
+ this.logger.info("EventSource SSE connection established");
17077
+ this.reconnectAttempts = 0;
17078
+ this.emit("connected");
17079
+ });
17080
+ this.eventSource.addEventListener("message", (event) => {
17081
+ this.logger.debug("EventSource message received", { data: event.data });
17082
+ try {
17083
+ const data = JSON.parse(event.data);
17084
+ this.handleMessage(data);
17085
+ } catch (error) {
17086
+ this.logger.error("Error parsing EventSource message", { error, data: event.data });
17087
+ }
17088
+ });
17089
+ this.eventSource.addEventListener("error", (event) => {
17090
+ this.logger.error("EventSource error", { event });
17091
+ if (!this.isIntentionallyClosed) {
17092
+ this.emit("disconnected");
17093
+ this.handleReconnection();
17094
+ }
17095
+ });
17096
+ this.eventSource.addEventListener("transcription", (event) => {
17097
+ this.logger.debug("EventSource transcription event", { data: event.data });
17098
+ try {
17099
+ const data = JSON.parse(event.data);
17100
+ this.handleMessage({ ...data, type: "transcription" });
17101
+ } catch (error) {
17102
+ this.logger.error("Error parsing transcription event", { error, data: event.data });
17103
+ }
17104
+ });
17105
+ this.eventSource.addEventListener("call_event", (event) => {
17106
+ this.logger.debug("EventSource call_event", { data: event.data });
17107
+ try {
17108
+ const data = JSON.parse(event.data);
17109
+ this.handleMessage(data);
17110
+ } catch (error) {
17111
+ this.logger.error("Error parsing call_event", { error, data: event.data });
17112
+ }
17113
+ });
17114
+ }
16984
17115
  /**
16985
17116
  * Stop the SSE connection
16986
17117
  */
@@ -16991,6 +17122,11 @@ var TranscriptionService = class extends EventEmitter {
16991
17122
  clearTimeout(this.reconnectTimeout);
16992
17123
  delete this.reconnectTimeout;
16993
17124
  }
17125
+ if (this.eventSource) {
17126
+ this.eventSource.removeAllEventListeners();
17127
+ this.eventSource.close();
17128
+ delete this.eventSource;
17129
+ }
16994
17130
  if (this.reader) {
16995
17131
  this.reader.cancel();
16996
17132
  delete this.reader;
@@ -17404,6 +17540,14 @@ var Conversation = class extends EventEmitter {
17404
17540
  sipUrl: urls.sipUrl || "will be derived"
17405
17541
  });
17406
17542
  }
17543
+ /**
17544
+ * Set EventSource factory for React Native environments
17545
+ * Call this before initialize() to use EventSource instead of fetch streams for SSE
17546
+ */
17547
+ setEventSourceFactory(factory) {
17548
+ this.transcriptionService.setEventSourceFactory(factory);
17549
+ this.logger.debug("EventSource factory configured for transcription service");
17550
+ }
17407
17551
  /**
17408
17552
  * Initialize and start the conversation
17409
17553
  */
@@ -18101,6 +18245,10 @@ var AnganyVoice = class extends EventEmitter {
18101
18245
  this.conversations.delete(conversationId);
18102
18246
  this.emit("conversationEnded", conversationId);
18103
18247
  });
18248
+ if (this.config.eventSourceFactory) {
18249
+ this.logger.debug("Setting EventSource factory for conversation");
18250
+ conversation.setEventSourceFactory(this.config.eventSourceFactory);
18251
+ }
18104
18252
  try {
18105
18253
  this.logger.debug("Initializing conversation...");
18106
18254
  await conversation.initialize();