@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.cjs +89 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +89 -32
- package/dist/index.js.map +1 -1
- package/package.json +28 -18
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
|
-
|
|
16324
|
-
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
16851
|
+
this.logger.debug("Cleaning up local stream");
|
|
16816
16852
|
const tracks = this.localStream.getTracks();
|
|
16817
16853
|
tracks.forEach((track) => {
|
|
16818
|
-
this.logger.debug("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
16887
|
+
this.logger.warn("Error closing audio context", { error });
|
|
16852
16888
|
}
|
|
16853
16889
|
}
|
|
16854
16890
|
delete this.audioAnalyser;
|
|
16855
|
-
this.logger.
|
|
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`, {
|
|
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(
|
|
17107
|
-
|
|
17108
|
-
|
|
17109
|
-
|
|
17110
|
-
this.eventSource.addEventListener(
|
|
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(
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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
|
/**
|