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