@anganyai/voice-sdk 0.0.9 → 0.0.11

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.d.cts CHANGED
@@ -1408,6 +1408,7 @@ declare class Conversation extends EventEmitter<ConversationEvents> {
1408
1408
  }): Promise<void>;
1409
1409
  /**
1410
1410
  * Mute or unmute the user's microphone
1411
+ * This actually disables the local audio tracks to prevent sending audio
1411
1412
  */
1412
1413
  mute(muted: boolean): void;
1413
1414
  /**
package/dist/index.d.ts CHANGED
@@ -1408,6 +1408,7 @@ declare class Conversation extends EventEmitter<ConversationEvents> {
1408
1408
  }): Promise<void>;
1409
1409
  /**
1410
1410
  * Mute or unmute the user's microphone
1411
+ * This actually disables the local audio tracks to prevent sending audio
1411
1412
  */
1412
1413
  mute(muted: boolean): void;
1413
1414
  /**
package/dist/index.js CHANGED
@@ -16320,8 +16320,9 @@ var SipManager = class extends EventEmitter {
16320
16320
  { urls: "stun:stun1.l.google.com:19302" }
16321
16321
  ]
16322
16322
  },
16323
- iceGatheringTimeout: 2e3,
16324
- iceCheckingTimeout: 5e3
16323
+ // Reduced timeouts for faster connection (was 2000ms/5000ms)
16324
+ iceGatheringTimeout: 500,
16325
+ iceCheckingTimeout: 2e3
16325
16326
  },
16326
16327
  delegate: {
16327
16328
  onConnect: () => {
@@ -16486,7 +16487,7 @@ var SipManager = class extends EventEmitter {
16486
16487
  this.logger.debug("No active session to hang up");
16487
16488
  return;
16488
16489
  }
16489
- this.logger.info("\u{1F4F5} Hanging up call...");
16490
+ this.logger.info("Hanging up call...");
16490
16491
  try {
16491
16492
  const sessionState = this.currentSession.state;
16492
16493
  if (sessionState === "Established" || sessionState === "Establishing") {
@@ -16495,7 +16496,7 @@ var SipManager = class extends EventEmitter {
16495
16496
  this.logger.debug("Session already terminated, skipping BYE", { state: sessionState });
16496
16497
  }
16497
16498
  } catch (error) {
16498
- this.logger.warn("\u26A0\uFE0F Error sending BYE", { error });
16499
+ this.logger.warn("Error sending BYE", { error });
16499
16500
  }
16500
16501
  delete this.currentSession;
16501
16502
  this.cleanupAudioResources();
@@ -16731,13 +16732,48 @@ var SipManager = class extends EventEmitter {
16731
16732
  }
16732
16733
  }
16733
16734
  /**
16734
- * Mute or unmute the remote audio
16735
+ * Mute or unmute the remote audio (output/speaker)
16735
16736
  */
16736
16737
  setMuted(muted) {
16737
16738
  if (this.audioElement) {
16738
16739
  this.audioElement.muted = muted;
16739
- this.logger.debug("Audio mute state changed", { muted });
16740
+ this.logger.debug("Remote audio mute state changed", { muted });
16741
+ }
16742
+ }
16743
+ /**
16744
+ * Mute or unmute the local audio (microphone input)
16745
+ * This actually disables the audio tracks to prevent sending audio
16746
+ */
16747
+ setLocalAudioEnabled(enabled) {
16748
+ if (this.localStream) {
16749
+ this.localStream.getAudioTracks().forEach((track) => {
16750
+ track.enabled = enabled;
16751
+ this.logger.debug("Local audio track enabled state changed", {
16752
+ trackId: track.id,
16753
+ enabled: track.enabled
16754
+ });
16755
+ });
16756
+ }
16757
+ if (this.preAcquiredStream && this.preAcquiredStream !== this.localStream) {
16758
+ this.preAcquiredStream.getAudioTracks().forEach((track) => {
16759
+ track.enabled = enabled;
16760
+ this.logger.debug("Pre-acquired audio track enabled state changed", {
16761
+ trackId: track.id,
16762
+ enabled: track.enabled
16763
+ });
16764
+ });
16765
+ }
16766
+ this.logger.info("Local audio (microphone) " + (enabled ? "enabled" : "disabled"));
16767
+ }
16768
+ /**
16769
+ * Check if local audio is enabled
16770
+ */
16771
+ isLocalAudioEnabled() {
16772
+ if (this.localStream) {
16773
+ const tracks = this.localStream.getAudioTracks();
16774
+ return tracks.length > 0 && tracks.every((track) => track.enabled);
16740
16775
  }
16776
+ return false;
16741
16777
  }
16742
16778
  startAudioMonitoring() {
16743
16779
  if (!this.localStream || this.audioMonitorInterval) {
@@ -16790,16 +16826,16 @@ var SipManager = class extends EventEmitter {
16790
16826
  delete this.audioAnalyser;
16791
16827
  }
16792
16828
  cleanupAudioResources() {
16793
- this.logger.debug("\u{1F9F9} Performing complete audio resource cleanup...", {
16829
+ this.logger.debug("Performing audio resource cleanup", {
16794
16830
  platform: isReactNative() ? "react-native" : "browser"
16795
16831
  });
16796
16832
  this.stopAudioMonitoring();
16797
16833
  if (this.audioElement && isBrowser()) {
16798
- this.logger.debug("\u{1F9F9} Cleaning up audio element...");
16834
+ this.logger.debug("Cleaning up audio element");
16799
16835
  if (this.audioElement.srcObject) {
16800
16836
  const tracks = this.audioElement.srcObject.getTracks();
16801
16837
  tracks.forEach((track) => {
16802
- this.logger.debug("\u{1F6D1} Stopping remote track", { kind: track.kind });
16838
+ this.logger.debug("Stopping remote track", { kind: track.kind });
16803
16839
  track.stop();
16804
16840
  });
16805
16841
  this.audioElement.srcObject = null;
@@ -16812,29 +16848,29 @@ var SipManager = class extends EventEmitter {
16812
16848
  this.logger.debug("Audio element cleaned up");
16813
16849
  }
16814
16850
  if (this.localStream) {
16815
- this.logger.debug("\u{1F9F9} Cleaning up local stream...");
16851
+ this.logger.debug("Cleaning up local stream");
16816
16852
  const tracks = this.localStream.getTracks();
16817
16853
  tracks.forEach((track) => {
16818
- this.logger.debug("\u{1F6D1} Stopping local track", { kind: track.kind });
16854
+ this.logger.debug("Stopping local track", { kind: track.kind });
16819
16855
  track.stop();
16820
16856
  });
16821
16857
  delete this.localStream;
16822
16858
  }
16823
16859
  if (this.preAcquiredStream) {
16824
- this.logger.debug("\u{1F3A4} Stopping pre-acquired microphone stream...");
16860
+ this.logger.debug("Stopping pre-acquired microphone stream");
16825
16861
  const tracks = this.preAcquiredStream.getTracks();
16826
16862
  tracks.forEach((track) => {
16827
- this.logger.debug("\u{1F6D1} Stopping pre-acquired track", { kind: track.kind });
16863
+ this.logger.debug("Stopping pre-acquired track", { kind: track.kind });
16828
16864
  track.stop();
16829
16865
  });
16830
16866
  delete this.preAcquiredStream;
16831
16867
  }
16832
16868
  if (this.remoteStream) {
16833
- this.logger.debug("\u{1F9F9} Cleaning up remote stream...");
16869
+ this.logger.debug("Cleaning up remote stream");
16834
16870
  try {
16835
16871
  const tracks = this.remoteStream.getTracks();
16836
16872
  tracks.forEach((track) => {
16837
- this.logger.debug("\u{1F6D1} Stopping remote track", { kind: track.kind });
16873
+ this.logger.debug("Stopping remote track", { kind: track.kind });
16838
16874
  track.stop();
16839
16875
  });
16840
16876
  } catch (error) {
@@ -16844,15 +16880,15 @@ var SipManager = class extends EventEmitter {
16844
16880
  }
16845
16881
  if (this.audioContext) {
16846
16882
  try {
16847
- this.logger.debug("\u{1F3B5} Closing audio context...");
16883
+ this.logger.debug("Closing audio context");
16848
16884
  this.audioContext.close();
16849
16885
  delete this.audioContext;
16850
16886
  } catch (error) {
16851
- this.logger.warn("\u26A0\uFE0F Error closing audio context", { error });
16887
+ this.logger.warn("Error closing audio context", { error });
16852
16888
  }
16853
16889
  }
16854
16890
  delete this.audioAnalyser;
16855
- this.logger.info("\u2705 Audio resources cleanup completed");
16891
+ this.logger.debug("Audio resources cleanup completed");
16856
16892
  }
16857
16893
  startKeepAlive() {
16858
16894
  this.stopKeepAlive();
@@ -17075,7 +17111,10 @@ var TranscriptionService = class extends EventEmitter {
17075
17111
  }
17076
17112
  });
17077
17113
  const handleSSEEvent = (eventType, event) => {
17078
- this.logger.debug(`EventSource [${eventType}] received`, { data: event.data, type: event.type });
17114
+ this.logger.debug(`EventSource [${eventType}] received`, {
17115
+ data: event.data,
17116
+ type: event.type
17117
+ });
17079
17118
  if (!event.data) {
17080
17119
  this.logger.debug(`EventSource [${eventType}] has no data, skipping`);
17081
17120
  return;
@@ -17103,13 +17142,31 @@ var TranscriptionService = class extends EventEmitter {
17103
17142
  }
17104
17143
  });
17105
17144
  this.eventSource.addEventListener("message", (event) => handleSSEEvent("message", event));
17106
- this.eventSource.addEventListener("transcription", (event) => handleSSEEvent("transcription", event));
17107
- this.eventSource.addEventListener("call_event", (event) => handleSSEEvent("call_event", event));
17108
- this.eventSource.addEventListener("call_started", (event) => handleSSEEvent("call_started", event));
17109
- this.eventSource.addEventListener("call_ended", (event) => handleSSEEvent("call_ended", event));
17110
- this.eventSource.addEventListener("connected", (event) => handleSSEEvent("connected", event));
17145
+ this.eventSource.addEventListener(
17146
+ "transcription",
17147
+ (event) => handleSSEEvent("transcription", event)
17148
+ );
17149
+ this.eventSource.addEventListener(
17150
+ "call_event",
17151
+ (event) => handleSSEEvent("call_event", event)
17152
+ );
17153
+ this.eventSource.addEventListener(
17154
+ "call_started",
17155
+ (event) => handleSSEEvent("call_started", event)
17156
+ );
17157
+ this.eventSource.addEventListener(
17158
+ "call_ended",
17159
+ (event) => handleSSEEvent("call_ended", event)
17160
+ );
17161
+ this.eventSource.addEventListener(
17162
+ "connected",
17163
+ (event) => handleSSEEvent("connected", event)
17164
+ );
17111
17165
  this.eventSource.addEventListener("welcome", (event) => handleSSEEvent("welcome", event));
17112
- this.eventSource.addEventListener("heartbeat", (event) => handleSSEEvent("heartbeat", event));
17166
+ this.eventSource.addEventListener(
17167
+ "heartbeat",
17168
+ (event) => handleSSEEvent("heartbeat", event)
17169
+ );
17113
17170
  }
17114
17171
  /**
17115
17172
  * Stop the SSE connection
@@ -17551,11 +17608,10 @@ var Conversation = class extends EventEmitter {
17551
17608
  * Initialize and start the conversation
17552
17609
  */
17553
17610
  async initialize() {
17554
- this.logger.debug("=== CONVERSATION INITIALIZATION START ===");
17611
+ this.logger.debug("Initializing conversation");
17555
17612
  try {
17556
17613
  this.setState("connecting");
17557
17614
  this.startTime = /* @__PURE__ */ new Date();
17558
- this.logger.debug("=== STEP 1: CHECKING AUTHENTICATION ===");
17559
17615
  const authStatus = this.authManager.getAuthStatus();
17560
17616
  this.logger.debug("Auth status received", {
17561
17617
  authenticated: authStatus.authenticated,
@@ -17567,8 +17623,7 @@ var Conversation = class extends EventEmitter {
17567
17623
  this.logger.error("Authentication check failed", { authStatus });
17568
17624
  throw new AuthenticationError("Not authenticated");
17569
17625
  }
17570
- this.logger.debug("\u2713 Authentication check passed");
17571
- this.logger.debug("=== STEP 2: GETTING ACCESS TOKEN (OPTIONAL) ===");
17626
+ this.logger.debug("Authentication check passed");
17572
17627
  let accessToken = authStatus.tokens?.accessToken;
17573
17628
  this.logger.debug("OAuth access token", { hasOAuthToken: !!accessToken });
17574
17629
  if (!accessToken) {
@@ -17593,11 +17648,10 @@ var Conversation = class extends EventEmitter {
17593
17648
  );
17594
17649
  } else {
17595
17650
  this.accessToken = accessToken;
17596
- this.logger.debug("\u2713 Access token obtained for API calls", {
17651
+ this.logger.debug("Access token obtained for API calls", {
17597
17652
  tokenLength: accessToken.length
17598
17653
  });
17599
17654
  }
17600
- this.logger.debug("=== STEP 3: ENSURING EPHEMERAL CREDENTIALS ===");
17601
17655
  if (!this.ephemeralCredentials) {
17602
17656
  this.logger.debug("Getting ephemeral credentials");
17603
17657
  this.ephemeralCredentials = this.authManager.getCachedEphemeralCredentials();
@@ -17613,7 +17667,7 @@ var Conversation = class extends EventEmitter {
17613
17667
  uriCount: this.ephemeralCredentials.sip?.uris?.length || 0
17614
17668
  });
17615
17669
  } else {
17616
- this.logger.debug("\u2713 Ephemeral credentials already available");
17670
+ this.logger.debug("Ephemeral credentials already available");
17617
17671
  }
17618
17672
  this.logger.debug("Raw ephemeral credentials", {
17619
17673
  sip: {
@@ -17737,6 +17791,7 @@ var Conversation = class extends EventEmitter {
17737
17791
  }
17738
17792
  }
17739
17793
  await this.sipManager.makeCall(callOptions);
17794
+ this.logger.debug("Conversation initialization complete");
17740
17795
  } catch (error) {
17741
17796
  this.logger.error("Failed to initialize conversation", { error });
17742
17797
  this.setState("error");
@@ -17792,10 +17847,12 @@ var Conversation = class extends EventEmitter {
17792
17847
  }
17793
17848
  /**
17794
17849
  * Mute or unmute the user's microphone
17850
+ * This actually disables the local audio tracks to prevent sending audio
17795
17851
  */
17796
17852
  mute(muted) {
17797
17853
  this.logger.debug("Setting user mute", { muted });
17798
17854
  this.userMuted = muted;
17855
+ this.sipManager.setLocalAudioEnabled(!muted);
17799
17856
  this.emit("userMuted", muted);
17800
17857
  }
17801
17858
  /**