@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 +149 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +160 -127
- package/dist/index.d.ts +160 -127
- package/dist/index.js +149 -1
- package/dist/index.js.map +1 -1
- package/package.json +18 -28
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();
|