@origonai/web-chat-sdk 0.1.0
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/README.md +423 -0
- package/dist/origon-chat-sdk.js +584 -0
- package/dist/origon-chat-sdk.js.map +1 -0
- package/package.json +51 -0
- package/src/call.js +622 -0
- package/src/chat.js +376 -0
- package/src/constants.js +10 -0
- package/src/http.js +122 -0
- package/src/index.js +58 -0
- package/src/utils.js +84 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
import { fetchEventSource as X } from "@microsoft/fetch-event-source";
|
|
2
|
+
function ee() {
|
|
3
|
+
const e = Date.now(), o = new Uint8Array(16);
|
|
4
|
+
crypto.getRandomValues(o), o[0] = e >> 40 & 255, o[1] = e >> 32 & 255, o[2] = e >> 24 & 255, o[3] = e >> 16 & 255, o[4] = e >> 8 & 255, o[5] = e & 255, o[6] = o[6] & 15 | 112, o[8] = o[8] & 63 | 128;
|
|
5
|
+
const s = [...o].map((a) => a.toString(16).padStart(2, "0")).join("");
|
|
6
|
+
return `${s.slice(0, 8)}-${s.slice(8, 12)}-${s.slice(12, 16)}-${s.slice(
|
|
7
|
+
16,
|
|
8
|
+
20
|
|
9
|
+
)}-${s.slice(20)}`;
|
|
10
|
+
}
|
|
11
|
+
function ne() {
|
|
12
|
+
if (localStorage.getItem("chatDeviceId"))
|
|
13
|
+
return localStorage.getItem("chatDeviceId");
|
|
14
|
+
const e = ee();
|
|
15
|
+
return localStorage.setItem("chatDeviceId", e), e;
|
|
16
|
+
}
|
|
17
|
+
async function te(e) {
|
|
18
|
+
return new Promise((o) => setTimeout(o, e));
|
|
19
|
+
}
|
|
20
|
+
function oe(e) {
|
|
21
|
+
let o;
|
|
22
|
+
try {
|
|
23
|
+
const s = new URL(e);
|
|
24
|
+
o = `wss://${s.hostname}${s.pathname}/audio`;
|
|
25
|
+
} catch (s) {
|
|
26
|
+
console.error("getCallServerEndpoint: Invalid base URL: ", e);
|
|
27
|
+
}
|
|
28
|
+
return o;
|
|
29
|
+
}
|
|
30
|
+
const k = {
|
|
31
|
+
BOT: "assistant",
|
|
32
|
+
// this can be automated or LLM AI Agent response
|
|
33
|
+
USER: "user",
|
|
34
|
+
// this is widget user
|
|
35
|
+
AGENT: "agent",
|
|
36
|
+
// this is human agent (dock side)
|
|
37
|
+
SYSTEM: "system"
|
|
38
|
+
// this is system message, for ex "Agent joined" / "Agent left"
|
|
39
|
+
};
|
|
40
|
+
function _(e = {}) {
|
|
41
|
+
return {
|
|
42
|
+
credentials: void 0,
|
|
43
|
+
authenticated: !1,
|
|
44
|
+
configData: void 0,
|
|
45
|
+
sessionId: void 0,
|
|
46
|
+
requestId: void 0,
|
|
47
|
+
sseUrl: void 0,
|
|
48
|
+
abortController: void 0,
|
|
49
|
+
liveAgent: !1,
|
|
50
|
+
lastStreamId: void 0,
|
|
51
|
+
messages: [],
|
|
52
|
+
callbacks: e
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
let t = _();
|
|
56
|
+
function ye(e) {
|
|
57
|
+
t.callbacks = { ...t.callbacks, ...e };
|
|
58
|
+
}
|
|
59
|
+
function be(e) {
|
|
60
|
+
console.log("Initializing chat...", e), t.credentials = e, e.token && (t.authenticated = !0);
|
|
61
|
+
}
|
|
62
|
+
function se() {
|
|
63
|
+
return t.credentials;
|
|
64
|
+
}
|
|
65
|
+
function ae(e) {
|
|
66
|
+
var o, s;
|
|
67
|
+
e && e !== t.sessionId && (t.sessionId = e, (s = (o = t.callbacks).onSessionUpdate) == null || s.call(o, e));
|
|
68
|
+
}
|
|
69
|
+
async function Ee(e = {}) {
|
|
70
|
+
var o;
|
|
71
|
+
try {
|
|
72
|
+
console.log("startChat: ", e, t);
|
|
73
|
+
let s = null;
|
|
74
|
+
t.authenticated ? s = t.configData : (s = await le(t.credentials), t.authenticated = !0, t.configData = s);
|
|
75
|
+
let a = [];
|
|
76
|
+
if (e.sessionId) {
|
|
77
|
+
const g = await de(e.sessionId);
|
|
78
|
+
a = ((o = g == null ? void 0 : g.sessionHistory) != null ? o : []).map((r) => ({
|
|
79
|
+
id: r.id,
|
|
80
|
+
text: r.text,
|
|
81
|
+
role: r.youtubeVideo ? k.BOT : r.role,
|
|
82
|
+
timestamp: r.timestamp,
|
|
83
|
+
video: r.youtubeVideo,
|
|
84
|
+
channel: r.channel,
|
|
85
|
+
done: !0
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
const u = new URLSearchParams({
|
|
89
|
+
externalId: A()
|
|
90
|
+
});
|
|
91
|
+
return t.sseUrl = `${t.credentials.endpoint}?${u.toString()}`, t.sessionId = e.sessionId, t.messages = a, console.log("Chat initiated successfully"), {
|
|
92
|
+
sessionId: t.sessionId,
|
|
93
|
+
messages: a,
|
|
94
|
+
configData: s
|
|
95
|
+
};
|
|
96
|
+
} catch (s) {
|
|
97
|
+
throw console.error(`Failed to start chat: ${s.message}`), K(), s;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function ve() {
|
|
101
|
+
K();
|
|
102
|
+
}
|
|
103
|
+
function K() {
|
|
104
|
+
t.abortController && t.abortController.abort();
|
|
105
|
+
const { callbacks: e, credentials: o } = t;
|
|
106
|
+
t = _(e), t.credentials = o, console.log("Chat session cleaned up");
|
|
107
|
+
}
|
|
108
|
+
function A() {
|
|
109
|
+
var e;
|
|
110
|
+
return (e = t.credentials) != null && e.externalId ? t.credentials.externalId : ne();
|
|
111
|
+
}
|
|
112
|
+
function Ae({ text: e, html: o }) {
|
|
113
|
+
return new Promise((s, a) => {
|
|
114
|
+
(async () => {
|
|
115
|
+
var u, g, r, h, l, w, T;
|
|
116
|
+
try {
|
|
117
|
+
const y = {
|
|
118
|
+
role: k.USER,
|
|
119
|
+
text: e,
|
|
120
|
+
html: o,
|
|
121
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
122
|
+
};
|
|
123
|
+
if (t.messages = [...t.messages, y], (g = (u = t.callbacks).onMessagesUpdate) == null || g.call(u, [...t.messages]), await te(200), t.liveAgent)
|
|
124
|
+
s(t.sessionId);
|
|
125
|
+
else {
|
|
126
|
+
const d = {
|
|
127
|
+
role: k.BOT,
|
|
128
|
+
text: "",
|
|
129
|
+
loading: !0
|
|
130
|
+
};
|
|
131
|
+
t.messages = [...t.messages, d], (h = (r = t.callbacks).onMessagesUpdate) == null || h.call(r, [...t.messages]);
|
|
132
|
+
}
|
|
133
|
+
const C = new URL(t.sseUrl);
|
|
134
|
+
t.sessionId && C.searchParams.set("sessionId", t.sessionId), t.requestId && C.searchParams.set("requestId", t.requestId), t.lastStreamId = void 0, t.abortController = new AbortController();
|
|
135
|
+
const I = {
|
|
136
|
+
"Content-Type": "application/json"
|
|
137
|
+
};
|
|
138
|
+
(l = t.credentials) != null && l.token && (I.Authorization = `Bearer ${t.credentials.token}`), await X(C.toString(), {
|
|
139
|
+
method: "POST",
|
|
140
|
+
headers: I,
|
|
141
|
+
body: JSON.stringify({
|
|
142
|
+
message: e,
|
|
143
|
+
html: o
|
|
144
|
+
}),
|
|
145
|
+
signal: t.abortController.signal,
|
|
146
|
+
onopen: async (d) => {
|
|
147
|
+
if (!d.ok)
|
|
148
|
+
throw console.error("Failed to send message bad response: ", d), new Error("Failed to send message");
|
|
149
|
+
},
|
|
150
|
+
onmessage: (d) => {
|
|
151
|
+
var R, $, O, U, P, x, D, M, N, L, q, F, J, z, G, W, B, H;
|
|
152
|
+
console.log("Event: ", d);
|
|
153
|
+
const i = JSON.parse(d.data);
|
|
154
|
+
if (i.status === "connected")
|
|
155
|
+
t.sessionId = i.sessionId, t.requestId = i.requestId, t.liveAgent && s(t.sessionId);
|
|
156
|
+
else if (i.agent) {
|
|
157
|
+
t.liveAgent = !0;
|
|
158
|
+
const { type: f, data: c } = i.agent;
|
|
159
|
+
switch (f) {
|
|
160
|
+
case "typing":
|
|
161
|
+
($ = (R = t.callbacks).onTyping) == null || $.call(R, !0), (U = (O = t.callbacks).onLiveAgentMode) == null || U.call(O, !0);
|
|
162
|
+
break;
|
|
163
|
+
case "typingOff":
|
|
164
|
+
(x = (P = t.callbacks).onTyping) == null || x.call(P, !1), (M = (D = t.callbacks).onLiveAgentMode) == null || M.call(D, !0);
|
|
165
|
+
break;
|
|
166
|
+
case "message":
|
|
167
|
+
if (c.role !== k.USER) {
|
|
168
|
+
t.messages = t.messages.filter((b) => !b.loading), t.messages = [...t.messages, c];
|
|
169
|
+
const m = c.action === "ended" || c.action === "left";
|
|
170
|
+
m && (t.liveAgent = !1), (L = (N = t.callbacks).onMessagesUpdate) == null || L.call(N, [...t.messages]), (F = (q = t.callbacks).onLiveAgentMode) == null || F.call(q, !m);
|
|
171
|
+
}
|
|
172
|
+
(c.action === "ended" || c.action === "left") && (t.liveAgent = !1);
|
|
173
|
+
break;
|
|
174
|
+
default:
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
} else if (i.message !== void 0) {
|
|
178
|
+
let f = t.messages;
|
|
179
|
+
i.streamId !== void 0 && (t.lastStreamId === void 0 ? t.lastStreamId = i.streamId : i.streamId !== t.lastStreamId && (t.lastStreamId = i.streamId, f = [
|
|
180
|
+
...f,
|
|
181
|
+
{
|
|
182
|
+
role: k.BOT,
|
|
183
|
+
text: "",
|
|
184
|
+
loading: !0
|
|
185
|
+
}
|
|
186
|
+
])), t.messages = f.map((c, m) => {
|
|
187
|
+
var b;
|
|
188
|
+
return m === f.length - 1 ? {
|
|
189
|
+
...c,
|
|
190
|
+
loading: !1,
|
|
191
|
+
text: (c.text || "") + i.message,
|
|
192
|
+
done: (b = i.done) != null ? b : c.done
|
|
193
|
+
} : c;
|
|
194
|
+
}), (z = (J = t.callbacks).onMessagesUpdate) == null || z.call(J, [...t.messages]), i.done && s(t.sessionId), t.sessionId = (G = i.session_id) != null ? G : t.sessionId, t.requestId = (W = i.requestId) != null ? W : t.requestId;
|
|
195
|
+
} else if (i.error) {
|
|
196
|
+
const f = "Failed to connect to the system";
|
|
197
|
+
t.messages = t.messages.map((c, m) => m === t.messages.length - 1 ? {
|
|
198
|
+
...c,
|
|
199
|
+
loading: !1,
|
|
200
|
+
errorText: f
|
|
201
|
+
} : c), (H = (B = t.callbacks).onMessagesUpdate) == null || H.call(B, [...t.messages]), a(new Error(f));
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
onerror: (d) => {
|
|
205
|
+
throw d;
|
|
206
|
+
},
|
|
207
|
+
openWhenHidden: !0
|
|
208
|
+
});
|
|
209
|
+
} catch (y) {
|
|
210
|
+
console.error("Failed to send message: ", y);
|
|
211
|
+
const C = "Failed to connect to the system";
|
|
212
|
+
t.messages = t.messages.map((I, d) => d === t.messages.length - 1 ? {
|
|
213
|
+
...I,
|
|
214
|
+
loading: !1,
|
|
215
|
+
errorText: C,
|
|
216
|
+
done: !0
|
|
217
|
+
} : I), (T = (w = t.callbacks).onMessagesUpdate) == null || T.call(w, [...t.messages]), a(y);
|
|
218
|
+
}
|
|
219
|
+
})();
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
const re = "Something went wrong initializing the chat", ie = "Chat SDK not initialized";
|
|
223
|
+
let j = {
|
|
224
|
+
endpoint: null
|
|
225
|
+
};
|
|
226
|
+
function ce(e) {
|
|
227
|
+
j = {
|
|
228
|
+
endpoint: e.endpoint
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
async function le(e) {
|
|
232
|
+
const { endpoint: o } = e, s = `${o}/config`, a = await fetch(s, {
|
|
233
|
+
method: "GET",
|
|
234
|
+
headers: {
|
|
235
|
+
"Content-Type": "application/json"
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
if (!a.ok) {
|
|
239
|
+
const r = await a.json();
|
|
240
|
+
throw new Error((r == null ? void 0 : r.error) || re);
|
|
241
|
+
}
|
|
242
|
+
const g = (await a.json()).data;
|
|
243
|
+
return ce({ endpoint: o }), g;
|
|
244
|
+
}
|
|
245
|
+
async function Te() {
|
|
246
|
+
const e = new URLSearchParams({
|
|
247
|
+
externalId: A()
|
|
248
|
+
}), o = await V(`/sessions?${e.toString()}`, "GET");
|
|
249
|
+
if (!o.ok)
|
|
250
|
+
throw new Error("Unable to load history, please try again later");
|
|
251
|
+
return o.json();
|
|
252
|
+
}
|
|
253
|
+
async function de(e) {
|
|
254
|
+
const o = new URLSearchParams({
|
|
255
|
+
sessionId: e
|
|
256
|
+
}), s = await V(`/session?${o.toString()}`, "GET");
|
|
257
|
+
if (!s.ok)
|
|
258
|
+
throw new Error("Unable to load messages, please try again later");
|
|
259
|
+
return s.json();
|
|
260
|
+
}
|
|
261
|
+
async function V(e, o = "GET", s = null) {
|
|
262
|
+
const { endpoint: a } = j;
|
|
263
|
+
if (!a)
|
|
264
|
+
throw new Error(ie);
|
|
265
|
+
const u = `${a}${e}`;
|
|
266
|
+
return fetch(u, {
|
|
267
|
+
headers: {
|
|
268
|
+
"Content-Type": "application/json"
|
|
269
|
+
},
|
|
270
|
+
method: o,
|
|
271
|
+
body: s ? JSON.stringify(s) : null
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
function Q(e = {}) {
|
|
275
|
+
return {
|
|
276
|
+
sessionId: void 0,
|
|
277
|
+
socket: null,
|
|
278
|
+
peerConnection: null,
|
|
279
|
+
localStream: null,
|
|
280
|
+
remoteStream: null,
|
|
281
|
+
remoteAudio: null,
|
|
282
|
+
isMuted: !1,
|
|
283
|
+
callStatus: "disconnected",
|
|
284
|
+
pingInterval: null,
|
|
285
|
+
pingCount: 0,
|
|
286
|
+
lastPongTime: null,
|
|
287
|
+
callbacks: e,
|
|
288
|
+
localIceCandidates: [],
|
|
289
|
+
pendingRemoteIceCandidates: []
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
let n = Q();
|
|
293
|
+
const ue = {
|
|
294
|
+
iceServers: [{ urls: "stun:stun.l.google.com:19302" }, { urls: "stun:stun1.l.google.com:19302" }]
|
|
295
|
+
};
|
|
296
|
+
function Re(e) {
|
|
297
|
+
n.callbacks = { ...n.callbacks, ...e };
|
|
298
|
+
}
|
|
299
|
+
function Y() {
|
|
300
|
+
n.peerConnection && (n.peerConnection.close(), n.peerConnection = null), n.localStream && (n.localStream.getTracks().forEach((o) => o.stop()), n.localStream = null), n.remoteStream && (n.remoteStream = null), n.remoteAudio && (n.remoteAudio.srcObject = null, n.remoteAudio.parentNode && n.remoteAudio.parentNode.removeChild(n.remoteAudio), n.remoteAudio = null), n.socket && (n.socket.close(), n.socket = null), v();
|
|
301
|
+
const e = n.callbacks;
|
|
302
|
+
n = Q(e), console.log("Call session cleaned up");
|
|
303
|
+
}
|
|
304
|
+
function p(e) {
|
|
305
|
+
var o, s;
|
|
306
|
+
n.callStatus = e, (s = (o = n.callbacks).onCallStatus) == null || s.call(o, e);
|
|
307
|
+
}
|
|
308
|
+
function E(e) {
|
|
309
|
+
var o, s;
|
|
310
|
+
(s = (o = n.callbacks).onCallError) == null || s.call(o, e);
|
|
311
|
+
}
|
|
312
|
+
function v() {
|
|
313
|
+
n.pingInterval && (clearInterval(n.pingInterval), n.pingInterval = null);
|
|
314
|
+
}
|
|
315
|
+
function ge() {
|
|
316
|
+
v(), n.pingInterval = setInterval(() => {
|
|
317
|
+
if (n.socket && n.socket.readyState === WebSocket.OPEN) {
|
|
318
|
+
n.pingCount++;
|
|
319
|
+
const e = {
|
|
320
|
+
type: "ping",
|
|
321
|
+
timestamp: Date.now(),
|
|
322
|
+
count: n.pingCount
|
|
323
|
+
};
|
|
324
|
+
S(e), console.log(`Sending keep-alive ping #${n.pingCount}`);
|
|
325
|
+
} else
|
|
326
|
+
console.log("Socket not open, stopping ping interval"), v();
|
|
327
|
+
}, 1e4);
|
|
328
|
+
}
|
|
329
|
+
function fe() {
|
|
330
|
+
n.lastPongTime = Date.now(), console.log(`Received pong #${n.pingCount}`);
|
|
331
|
+
}
|
|
332
|
+
function S(e) {
|
|
333
|
+
if (!n.socket) {
|
|
334
|
+
console.error("Failed to send event: no socket instance");
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (n.socket.readyState !== WebSocket.OPEN) {
|
|
338
|
+
console.error("Failed to send event: socket state not open ", e);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
n.socket.send(JSON.stringify(e));
|
|
342
|
+
}
|
|
343
|
+
async function pe() {
|
|
344
|
+
try {
|
|
345
|
+
n.localStream = await navigator.mediaDevices.getUserMedia({
|
|
346
|
+
audio: !0,
|
|
347
|
+
video: !1
|
|
348
|
+
}), console.log("Got audio media");
|
|
349
|
+
} catch (e) {
|
|
350
|
+
throw console.error(`Failed to get audio media: ${e.message}`), e;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function me() {
|
|
354
|
+
n.peerConnection = new RTCPeerConnection(ue), n.peerConnection.onicecandidate = (e) => {
|
|
355
|
+
if (e.candidate) {
|
|
356
|
+
const o = JSON.stringify(e.candidate);
|
|
357
|
+
n.peerConnection && n.peerConnection.remoteDescription ? (S({
|
|
358
|
+
type: "ice",
|
|
359
|
+
data: {
|
|
360
|
+
candidate: o
|
|
361
|
+
}
|
|
362
|
+
}), console.log("Sent ICE candidate immediately")) : (n.localIceCandidates.push(o), console.log("Queued local ICE candidate"));
|
|
363
|
+
}
|
|
364
|
+
}, n.peerConnection.ontrack = (e) => {
|
|
365
|
+
console.log("Received remote audio stream"), n.remoteStream = e.streams[0], n.remoteAudio || (n.remoteAudio = document.createElement("audio"), n.remoteAudio.autoplay = !0, n.remoteAudio.controls = !1, document.body.appendChild(n.remoteAudio)), n.remoteAudio.srcObject = n.remoteStream, n.remoteAudio.play().then(() => console.log("🔊 remote audio playing")).catch((o) => console.error("❌ playback error:", o));
|
|
366
|
+
}, n.peerConnection.onconnectionstatechange = () => {
|
|
367
|
+
const e = n.peerConnection.connectionState;
|
|
368
|
+
console.log(`Connection state: ${e}`), e === "connected" ? p("connected") : (e === "disconnected" || e === "closed") && (p("disconnected"), Z());
|
|
369
|
+
}, n.peerConnection.oniceconnectionstatechange = () => {
|
|
370
|
+
console.log(`ICE connection state: ${n.peerConnection.iceConnectionState}`);
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
function Se(e) {
|
|
374
|
+
return new Promise((o, s) => {
|
|
375
|
+
if (n.socket && (n.socket.readyState === WebSocket.CONNECTING || n.socket.readyState === WebSocket.OPEN)) {
|
|
376
|
+
console.log("Socket in connecting/open state, returning."), o(n.socket.readyState === WebSocket.OPEN);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
console.log("Initializing socket connection..");
|
|
380
|
+
const a = se();
|
|
381
|
+
if (!a || !a.endpoint) {
|
|
382
|
+
s(new Error("SDK not initialized. Please initialize SDK first."));
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const u = oe(a.endpoint);
|
|
386
|
+
if (!u) {
|
|
387
|
+
s(
|
|
388
|
+
new Error(
|
|
389
|
+
"Invalid endpoint while initializing SDK. Please check the endpoint and try again."
|
|
390
|
+
)
|
|
391
|
+
);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const g = A(), r = new URLSearchParams({
|
|
395
|
+
externalId: g
|
|
396
|
+
});
|
|
397
|
+
e.sessionId && r.set("sessionId", e.sessionId), a.token && r.set("token", a.token);
|
|
398
|
+
const h = `${u}?${r.toString()}`;
|
|
399
|
+
n.socket = new WebSocket(h), n.socket.onopen = (l) => {
|
|
400
|
+
console.log("Socket connection established: ", l), ge(), o(!0);
|
|
401
|
+
}, n.socket.onmessage = (l) => {
|
|
402
|
+
const w = JSON.parse(l.data);
|
|
403
|
+
Ce(w);
|
|
404
|
+
}, n.socket.onerror = (l) => {
|
|
405
|
+
console.error("Socket error: ", l), p("error"), E(l.message || "Unable to connect voice"), s(l);
|
|
406
|
+
}, n.socket.onclose = (l) => {
|
|
407
|
+
console.log("Socket connection closed: ", l), v();
|
|
408
|
+
};
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
function Ce(e) {
|
|
412
|
+
switch (console.log("Handling socket server event: ", e), e.type) {
|
|
413
|
+
case "pong":
|
|
414
|
+
fe();
|
|
415
|
+
break;
|
|
416
|
+
case "answer":
|
|
417
|
+
Ie(e.data);
|
|
418
|
+
break;
|
|
419
|
+
case "ice":
|
|
420
|
+
ke(e.data);
|
|
421
|
+
break;
|
|
422
|
+
case "renegotiationOffer":
|
|
423
|
+
he(e.data);
|
|
424
|
+
break;
|
|
425
|
+
case "end":
|
|
426
|
+
Z();
|
|
427
|
+
break;
|
|
428
|
+
case "error":
|
|
429
|
+
p("error"), E(e.error || "Unable to connect voice");
|
|
430
|
+
break;
|
|
431
|
+
default:
|
|
432
|
+
console.log("Unknown call event type: ", e.type);
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async function Ie(e) {
|
|
437
|
+
try {
|
|
438
|
+
if (console.log("Received answer"), n.sessionId = e.sessionId, ae(e.sessionId), n.peerConnection) {
|
|
439
|
+
const o = new RTCSessionDescription({
|
|
440
|
+
type: "answer",
|
|
441
|
+
sdp: e.sdp
|
|
442
|
+
});
|
|
443
|
+
console.log("Setting remote description answer: ", o), await n.peerConnection.setRemoteDescription(o), console.log("Remote description set");
|
|
444
|
+
for (const s of n.localIceCandidates)
|
|
445
|
+
S({
|
|
446
|
+
type: "ice",
|
|
447
|
+
data: {
|
|
448
|
+
candidate: s
|
|
449
|
+
}
|
|
450
|
+
}), console.log("Sent queued local ICE candidate");
|
|
451
|
+
n.localIceCandidates = [];
|
|
452
|
+
for (const s of n.pendingRemoteIceCandidates)
|
|
453
|
+
try {
|
|
454
|
+
const a = new RTCIceCandidate(JSON.parse(s));
|
|
455
|
+
await n.peerConnection.addIceCandidate(a), console.log("Added pending remote ICE candidate");
|
|
456
|
+
} catch (a) {
|
|
457
|
+
console.error(`Failed to add pending ICE candidate: ${a.message}`);
|
|
458
|
+
}
|
|
459
|
+
n.pendingRemoteIceCandidates = [];
|
|
460
|
+
}
|
|
461
|
+
} catch (o) {
|
|
462
|
+
console.error(`Failed to handle answer: ${o.message}`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
async function ke(e) {
|
|
466
|
+
try {
|
|
467
|
+
if (n.peerConnection) {
|
|
468
|
+
if (!n.peerConnection.remoteDescription) {
|
|
469
|
+
n.pendingRemoteIceCandidates.push(e.candidate), console.log("Queued remote ICE candidate - remote description not set");
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
const o = new RTCIceCandidate(JSON.parse(e.candidate));
|
|
473
|
+
await n.peerConnection.addIceCandidate(o), console.log("Added ICE candidate");
|
|
474
|
+
}
|
|
475
|
+
} catch (o) {
|
|
476
|
+
console.error(`Failed to add ICE candidate: ${o.message}`);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
async function he(e) {
|
|
480
|
+
try {
|
|
481
|
+
if (console.log("Received renegotiation offer"), n.peerConnection) {
|
|
482
|
+
const o = new RTCSessionDescription({
|
|
483
|
+
type: "offer",
|
|
484
|
+
sdp: e.sdp
|
|
485
|
+
});
|
|
486
|
+
console.log("Setting remote description offer: ", o), await n.peerConnection.setRemoteDescription(o), console.log("Remote description set");
|
|
487
|
+
const s = await n.peerConnection.createAnswer();
|
|
488
|
+
await n.peerConnection.setLocalDescription(s), S({
|
|
489
|
+
type: "renegotiationAnswer",
|
|
490
|
+
data: {
|
|
491
|
+
sdp: s.sdp
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
} catch (o) {
|
|
496
|
+
console.error(`Failed to handle renegotiation offer: ${o.message}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
async function $e(e = {}) {
|
|
500
|
+
try {
|
|
501
|
+
if (n.callStatus === "connecting" || n.callStatus === "connected") {
|
|
502
|
+
console.log(`Call already in ${n.callStatus} state`);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
console.log("Starting audio call..."), p("connecting"), E(null), n.sessionId = e.sessionId, await pe(), me(), n.localStream.getTracks().forEach((s) => {
|
|
506
|
+
n.peerConnection.addTrack(s, n.localStream), console.log(`Added ${s.kind} track`);
|
|
507
|
+
}), await Se(e);
|
|
508
|
+
const o = await n.peerConnection.createOffer();
|
|
509
|
+
await n.peerConnection.setLocalDescription(o), S({
|
|
510
|
+
type: "offer",
|
|
511
|
+
data: {
|
|
512
|
+
sdp: o.sdp
|
|
513
|
+
}
|
|
514
|
+
}), console.log("Call initiated successfully");
|
|
515
|
+
} catch (o) {
|
|
516
|
+
console.log("error: ", o), console.error(`Failed to start call: ${o.message}`), p("error"), E(o.message || "Unable to connect voice"), Y();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
function Z() {
|
|
520
|
+
S({
|
|
521
|
+
type: "end"
|
|
522
|
+
}), n.socket && (n.socket.close(), n.socket = null), p("disconnected"), n.peerConnection && (n.peerConnection.close(), n.peerConnection = null), n.localStream && (n.localStream.getTracks().forEach((e) => e.stop()), n.localStream = null), Y();
|
|
523
|
+
}
|
|
524
|
+
function Oe() {
|
|
525
|
+
if (n.localStream) {
|
|
526
|
+
const e = n.localStream.getAudioTracks()[0];
|
|
527
|
+
if (e)
|
|
528
|
+
return e.enabled = !e.enabled, n.isMuted = !e.enabled, console.log(`Audio ${n.isMuted ? "muted" : "unmuted"}`), n.isMuted;
|
|
529
|
+
}
|
|
530
|
+
return !1;
|
|
531
|
+
}
|
|
532
|
+
function Ue() {
|
|
533
|
+
return n.localStream;
|
|
534
|
+
}
|
|
535
|
+
function Pe() {
|
|
536
|
+
return new Promise((e, o) => {
|
|
537
|
+
if (!n.peerConnection) {
|
|
538
|
+
o(new Error("no peer connection"));
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
n.peerConnection.getStats().then((s) => {
|
|
542
|
+
s.forEach((a) => {
|
|
543
|
+
a.type == "inbound-rtp" && e(a.totalAudioEnergy);
|
|
544
|
+
}), o(new Error("no inbound-rtp stats found"));
|
|
545
|
+
}).catch((s) => {
|
|
546
|
+
o(s);
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
function xe() {
|
|
551
|
+
return new Promise((e, o) => {
|
|
552
|
+
if (!n.peerConnection) {
|
|
553
|
+
o(new Error("no peer connection"));
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
n.peerConnection.getStats().then((s) => {
|
|
557
|
+
s.forEach((a) => {
|
|
558
|
+
a.type == "outbound-rtp" && e(a.totalAudioEnergy);
|
|
559
|
+
}), o(new Error("no outbound-rtp stats found"));
|
|
560
|
+
}).catch((s) => {
|
|
561
|
+
o(s);
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
export {
|
|
566
|
+
k as MESSAGE_ROLES,
|
|
567
|
+
le as authenticate,
|
|
568
|
+
ce as configure,
|
|
569
|
+
ve as disconnect,
|
|
570
|
+
Z as disconnectCall,
|
|
571
|
+
Te as getHistory,
|
|
572
|
+
Pe as getInboundAudioEnergy,
|
|
573
|
+
Ue as getLocalStream,
|
|
574
|
+
de as getMessages,
|
|
575
|
+
xe as getOutboundAudioEnergy,
|
|
576
|
+
be as initialize,
|
|
577
|
+
Ae as sendMessage,
|
|
578
|
+
Re as setCallCallbacks,
|
|
579
|
+
ye as setCallbacks,
|
|
580
|
+
$e as startCall,
|
|
581
|
+
Ee as startChat,
|
|
582
|
+
Oe as toggleMute
|
|
583
|
+
};
|
|
584
|
+
//# sourceMappingURL=origon-chat-sdk.js.map
|