@guava-ai/guava-sdk 0.37.0 → 0.39.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.
@@ -0,0 +1,74 @@
1
+ import { type ConnectingTone, type Tone } from "./tones.ts";
2
+ export { type ConnectingTone, JingleTone, RingbackTone, LeavingTone, type Tone } from "./tones.ts";
3
+ export type CallState = "not-started" | "starting" | "waiting-for-permission" | "connecting" | "connected" | "ended";
4
+ export type CallErrorCode = "MICROPHONE_ACCESS_FAILED" | "CONNECTION_FAILED" | "AUTHENTICATION_FAILED" | "PROTOCOL_ERROR" | "SERVER_ERROR" | "REMOTE_HANGUP" | "CONNECTION_TIMEOUT";
5
+ export declare class CallError extends Error {
6
+ readonly code: CallErrorCode;
7
+ constructor(code: CallErrorCode, message: string, options?: ErrorOptions);
8
+ }
9
+ export declare class Call {
10
+ private _state;
11
+ private _error?;
12
+ private readonly _stateHandlers;
13
+ private readonly _remoteStreamHandlers;
14
+ private readonly _messageHandlers;
15
+ private readonly _webrtcCode;
16
+ private readonly _sockUrl;
17
+ private readonly _remoteAudio;
18
+ private readonly _connectingTone?;
19
+ private readonly _leavingTone?;
20
+ private readonly _connectionTimeoutMs?;
21
+ private readonly _customPayload;
22
+ private _connectionTimer?;
23
+ private _sock?;
24
+ private readonly _chatSockUrl;
25
+ private readonly _chatSessionId;
26
+ private _chatSock?;
27
+ private _chatReady;
28
+ private _pendingChatMessages;
29
+ private _localStream?;
30
+ private _peerConnection?;
31
+ private _remoteStream?;
32
+ private _iceServers?;
33
+ private _pendingStart?;
34
+ constructor({ webrtcCode, baseUrl, connectingTone, leavingTone, connectionTimeoutMs, customPayload, }: {
35
+ /** Code used to authenticate with the signaling server. */
36
+ webrtcCode: string;
37
+ /** Base URL of the Guava server. Defaults to `https://app.goguava.ai/`. */
38
+ baseUrl?: string;
39
+ /** Played while the call is in the "connecting" state. Defaults to {@link JingleTone}. */
40
+ connectingTone?: ConnectingTone | "disabled";
41
+ /** Played when the call ends. Defaults to {@link LeavingTone}. */
42
+ leavingTone?: Tone | "disabled";
43
+ /** Max time in the "connecting" state before the call fails with CONNECTION_TIMEOUT. Defaults to 30 seconds. */
44
+ connectionTimeoutMs?: number | "disabled";
45
+ /** A custom payload that is forwarded to the agent at the start of the call. */
46
+ customPayload?: Record<string, unknown>;
47
+ });
48
+ get state(): CallState;
49
+ get error(): CallError | undefined;
50
+ get remoteStream(): MediaStream | undefined;
51
+ onStateChange(handler: (state: CallState) => void): () => void;
52
+ onRemoteStream(handler: (stream: MediaStream) => void): () => void;
53
+ /**
54
+ * Registers a handler for messages the agent sends with `call.send_webrtc_message()`.
55
+ * @param handler - Called with each message's payload.
56
+ * @returns A function that unregisters the handler.
57
+ */
58
+ onMessage(handler: (payload: Record<string, unknown>) => void): () => void;
59
+ private _setState;
60
+ start(): Promise<void>;
61
+ /**
62
+ * Sends a message to the agent, delivered to its `on_webrtc_message` handler.
63
+ * Messages sent before the message channel is ready are queued.
64
+ * @param payload - A JSON-serializable object.
65
+ */
66
+ sendMessage(payload: Record<string, unknown>): void;
67
+ private _openChatSocket;
68
+ hangup(): Promise<void>;
69
+ private _send;
70
+ private _onMessage;
71
+ private _connectPeer;
72
+ private _end;
73
+ private _teardown;
74
+ }
@@ -0,0 +1,398 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Call = exports.CallError = exports.LeavingTone = exports.RingbackTone = exports.JingleTone = void 0;
4
+ const tones_ts_1 = require("./tones.js");
5
+ var tones_ts_2 = require("./tones.js");
6
+ Object.defineProperty(exports, "JingleTone", { enumerable: true, get: function () { return tones_ts_2.JingleTone; } });
7
+ Object.defineProperty(exports, "RingbackTone", { enumerable: true, get: function () { return tones_ts_2.RingbackTone; } });
8
+ Object.defineProperty(exports, "LeavingTone", { enumerable: true, get: function () { return tones_ts_2.LeavingTone; } });
9
+ class CallError extends Error {
10
+ code;
11
+ constructor(code, message, options) {
12
+ super(message, options);
13
+ this.name = "CallError";
14
+ this.code = code;
15
+ }
16
+ }
17
+ exports.CallError = CallError;
18
+ // Used if the server doesn't send ICE servers with the auth reply.
19
+ const DEFAULT_ICE_SERVERS = [
20
+ { urls: ["stun:stun.l.google.com:19302", "stun:stun.sipgate.net:10000"] },
21
+ ];
22
+ const SOCKET_PROTOCOLS = {
23
+ "http:": "ws:",
24
+ "https:": "wss:",
25
+ "ws:": "ws:",
26
+ "wss:": "wss:",
27
+ };
28
+ class Call {
29
+ _state = "not-started";
30
+ _error;
31
+ _stateHandlers = new Set();
32
+ _remoteStreamHandlers = new Set();
33
+ _messageHandlers = new Set();
34
+ _webrtcCode;
35
+ _sockUrl;
36
+ _remoteAudio;
37
+ _connectingTone;
38
+ _leavingTone;
39
+ _connectionTimeoutMs;
40
+ _customPayload;
41
+ _connectionTimer;
42
+ _sock;
43
+ _chatSockUrl;
44
+ // Links the chat socket to this call's session on the server.
45
+ _chatSessionId = crypto.randomUUID();
46
+ _chatSock;
47
+ _chatReady = false;
48
+ // Messages sent before the chat socket is ready.
49
+ _pendingChatMessages = [];
50
+ _localStream;
51
+ _peerConnection;
52
+ _remoteStream;
53
+ _iceServers;
54
+ // Settles the promise returned by start().
55
+ _pendingStart;
56
+ constructor({ webrtcCode, baseUrl = "https://app.goguava.ai/", connectingTone = new tones_ts_1.JingleTone(), leavingTone = new tones_ts_1.LeavingTone(), connectionTimeoutMs = 30_000, customPayload = {}, }) {
57
+ this._webrtcCode = webrtcCode;
58
+ this._customPayload = customPayload;
59
+ if (connectingTone !== "disabled") {
60
+ this._connectingTone = connectingTone;
61
+ }
62
+ if (leavingTone !== "disabled") {
63
+ this._leavingTone = leavingTone;
64
+ }
65
+ if (connectionTimeoutMs !== "disabled") {
66
+ this._connectionTimeoutMs = connectionTimeoutMs;
67
+ }
68
+ this._sockUrl = new URL("/webrtc/", baseUrl);
69
+ const sockProtocol = SOCKET_PROTOCOLS[this._sockUrl.protocol];
70
+ if (sockProtocol === undefined) {
71
+ throw new Error(`Unsupported baseUrl protocol: ${this._sockUrl.protocol}`);
72
+ }
73
+ this._sockUrl.protocol = sockProtocol;
74
+ this._chatSockUrl = new URL("/webrtc-chat/", this._sockUrl);
75
+ this._remoteAudio = document.createElement("audio");
76
+ this._remoteAudio.autoplay = true;
77
+ }
78
+ get state() {
79
+ return this._state;
80
+ }
81
+ // Set if the call ended due to a failure.
82
+ get error() {
83
+ return this._error;
84
+ }
85
+ // Set once the remote audio track arrives, which happens before the call reaches "connected".
86
+ get remoteStream() {
87
+ return this._remoteStream;
88
+ }
89
+ // Returns a function that unregisters the handler.
90
+ onStateChange(handler) {
91
+ this._stateHandlers.add(handler);
92
+ return () => {
93
+ this._stateHandlers.delete(handler);
94
+ };
95
+ }
96
+ // Fires whenever the remote stream is replaced, including the first time it arrives.
97
+ // Returns a function that unregisters the handler.
98
+ onRemoteStream(handler) {
99
+ this._remoteStreamHandlers.add(handler);
100
+ return () => {
101
+ this._remoteStreamHandlers.delete(handler);
102
+ };
103
+ }
104
+ /**
105
+ * Registers a handler for messages the agent sends with `call.send_webrtc_message()`.
106
+ * @param handler - Called with each message's payload.
107
+ * @returns A function that unregisters the handler.
108
+ */
109
+ onMessage(handler) {
110
+ this._messageHandlers.add(handler);
111
+ return () => {
112
+ this._messageHandlers.delete(handler);
113
+ };
114
+ }
115
+ _setState(state) {
116
+ if (state === this._state) {
117
+ return;
118
+ }
119
+ if (state === "ended") {
120
+ this._leavingTone?.play();
121
+ }
122
+ this._state = state;
123
+ if (state === "connecting") {
124
+ this._connectingTone?.start();
125
+ if (this._connectionTimeoutMs !== undefined) {
126
+ this._connectionTimer = setTimeout(() => {
127
+ this._send({ type: "hangup" });
128
+ this._end(new CallError("CONNECTION_TIMEOUT", "Timed out connecting the call."));
129
+ }, this._connectionTimeoutMs);
130
+ }
131
+ }
132
+ else {
133
+ this._connectingTone?.stop();
134
+ clearTimeout(this._connectionTimer);
135
+ this._connectionTimer = undefined;
136
+ }
137
+ for (const handler of this._stateHandlers) {
138
+ handler(state);
139
+ }
140
+ }
141
+ async start() {
142
+ if (this._state !== "not-started") {
143
+ throw new Error(`start() was already called.`);
144
+ }
145
+ this._setState("starting");
146
+ // Add the audio element.
147
+ document.body.appendChild(this._remoteAudio);
148
+ // We start by requesting device permissions first. The idea is that, after permission has been granted,
149
+ // it makes sence to play a ringback, but it doesn't make sense to do so during the permission prompt.
150
+ const permissionTimer = setTimeout(() => {
151
+ this._setState("waiting-for-permission");
152
+ }, 500);
153
+ try {
154
+ this._localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
155
+ }
156
+ catch (error) {
157
+ const callError = new CallError("MICROPHONE_ACCESS_FAILED", "Failed to access microphone.", {
158
+ cause: error,
159
+ });
160
+ this._end(callError);
161
+ throw callError;
162
+ }
163
+ finally {
164
+ clearTimeout(permissionTimer);
165
+ }
166
+ // hangup() was called during the permission prompt.
167
+ if (this.state === "ended") {
168
+ this._teardown();
169
+ return;
170
+ }
171
+ // Now open and authenticate the signaling socket.
172
+ this._setState("connecting"); // UI can start playing rinback tones here.
173
+ const started = new Promise((resolve, reject) => {
174
+ this._pendingStart = { resolve, reject };
175
+ });
176
+ this._sock = new WebSocket(this._sockUrl);
177
+ this._sock.onopen = () => {
178
+ this._send({
179
+ type: "auth",
180
+ body: JSON.stringify({
181
+ webrtc_code: this._webrtcCode,
182
+ chat_session_id: this._chatSessionId,
183
+ }),
184
+ });
185
+ };
186
+ this._sock.onmessage = (event) => {
187
+ this._onMessage(JSON.parse(event.data));
188
+ };
189
+ this._sock.onclose = () => {
190
+ this._end(new CallError("CONNECTION_FAILED", "Signaling connection closed."));
191
+ };
192
+ await started;
193
+ }
194
+ /**
195
+ * Sends a message to the agent, delivered to its `on_webrtc_message` handler.
196
+ * Messages sent before the message channel is ready are queued.
197
+ * @param payload - A JSON-serializable object.
198
+ */
199
+ sendMessage(payload) {
200
+ if (this._state === "not-started" || this._state === "ended") {
201
+ throw new Error(`sendMessage() called while the call is ${this._state}.`);
202
+ }
203
+ const message = JSON.stringify({ type: "webrtc-message", payload });
204
+ if (this._chatReady && this._chatSock !== undefined) {
205
+ this._chatSock.send(message);
206
+ }
207
+ else {
208
+ this._pendingChatMessages.push(message);
209
+ }
210
+ }
211
+ _openChatSocket() {
212
+ this._chatSock = new WebSocket(this._chatSockUrl);
213
+ this._chatSock.onopen = () => {
214
+ this._chatSock?.send(JSON.stringify({ webrtc_code: this._webrtcCode, chat_session_id: this._chatSessionId }));
215
+ };
216
+ this._chatSock.onmessage = (event) => {
217
+ const message = JSON.parse(event.data);
218
+ // The server sends "ready" once the call session is found.
219
+ if (message.type === "ready" && !this._chatReady) {
220
+ this._chatReady = true;
221
+ for (const pending of this._pendingChatMessages) {
222
+ this._chatSock?.send(pending);
223
+ }
224
+ this._pendingChatMessages = [];
225
+ }
226
+ else if (message.command_type === "send-webrtc-message") {
227
+ for (const handler of this._messageHandlers) {
228
+ handler(message.payload ?? {});
229
+ }
230
+ }
231
+ };
232
+ }
233
+ async hangup() {
234
+ if (this._state === "not-started") {
235
+ throw new Error(`hangup() called before start().`);
236
+ }
237
+ if (this._state === "ended") {
238
+ return;
239
+ }
240
+ this._send({ type: "hangup" });
241
+ this._end();
242
+ }
243
+ _send(message) {
244
+ if (this._sock !== undefined && this._sock.readyState === WebSocket.OPEN) {
245
+ this._sock.send(JSON.stringify(message));
246
+ }
247
+ }
248
+ _onMessage(message) {
249
+ switch (message.type) {
250
+ case "auth":
251
+ if (message.body !== "OK") {
252
+ this._end(new CallError("AUTHENTICATION_FAILED", message.reason || "Authentication failed."));
253
+ return;
254
+ }
255
+ this._iceServers = message.ice_servers;
256
+ this._openChatSocket();
257
+ this._send({ type: "connect", body: { custom_payload: this._customPayload } });
258
+ void this._connectPeer();
259
+ break;
260
+ case "desc":
261
+ if (!this._peerConnection) {
262
+ this._end(new CallError("PROTOCOL_ERROR", "Received desc before the peer connection was created."));
263
+ return;
264
+ }
265
+ this._peerConnection.setRemoteDescription(message.body).catch((error) => {
266
+ this._end(new CallError("CONNECTION_FAILED", "Failed to set remote description.", {
267
+ cause: error,
268
+ }));
269
+ });
270
+ break;
271
+ case "candidate":
272
+ if (!this._peerConnection) {
273
+ this._end(new CallError("PROTOCOL_ERROR", "Received candidate before the peer connection was created."));
274
+ return;
275
+ }
276
+ this._peerConnection.addIceCandidate(message.body).catch((error) => {
277
+ console.warn("Failed to add ICE candidate:", error);
278
+ });
279
+ break;
280
+ case "hangup":
281
+ if (this._state === "connected") {
282
+ this._end();
283
+ }
284
+ else {
285
+ this._end(new CallError("REMOTE_HANGUP", "The remote hung up before the call connected."));
286
+ }
287
+ break;
288
+ case "error":
289
+ this._end(new CallError("SERVER_ERROR", message.body || "Unknown server error."));
290
+ break;
291
+ case "transfer":
292
+ this._end(new CallError("PROTOCOL_ERROR", "Transfers are not supported."));
293
+ break;
294
+ default:
295
+ console.warn("Unknown signaling message:", message);
296
+ }
297
+ }
298
+ async _connectPeer() {
299
+ if (!this._localStream) {
300
+ return;
301
+ }
302
+ this._peerConnection = new RTCPeerConnection({
303
+ iceServers: this._iceServers ?? DEFAULT_ICE_SERVERS,
304
+ });
305
+ this._peerConnection.onicecandidate = (event) => {
306
+ if (event.candidate) {
307
+ this._send({ type: "candidate", body: event.candidate });
308
+ }
309
+ };
310
+ this._peerConnection.ontrack = (event) => {
311
+ this._remoteStream = new MediaStream([event.track]);
312
+ this._remoteAudio.srcObject = this._remoteStream;
313
+ for (const handler of this._remoteStreamHandlers) {
314
+ handler(this._remoteStream);
315
+ }
316
+ };
317
+ this._peerConnection.onconnectionstatechange = () => {
318
+ if (this._peerConnection === undefined) {
319
+ return;
320
+ }
321
+ // "disconnected" is often transient, so wait for "failed" before ending the call.
322
+ if (this._peerConnection.connectionState === "connected") {
323
+ this._setState("connected");
324
+ if (this._pendingStart !== undefined) {
325
+ this._pendingStart.resolve();
326
+ this._pendingStart = undefined;
327
+ }
328
+ }
329
+ else if (this._peerConnection.connectionState === "failed") {
330
+ this._end(new CallError("CONNECTION_FAILED", "Peer connection failed."));
331
+ }
332
+ };
333
+ for (const track of this._localStream.getAudioTracks()) {
334
+ this._peerConnection.addTrack(track);
335
+ }
336
+ try {
337
+ await this._peerConnection.setLocalDescription();
338
+ }
339
+ catch (error) {
340
+ this._end(new CallError("CONNECTION_FAILED", "Failed to create offer.", { cause: error }));
341
+ return;
342
+ }
343
+ // The call may have ended while creating the offer.
344
+ if (this.state === "ended") {
345
+ return;
346
+ }
347
+ this._send({ type: "desc", body: this._peerConnection.localDescription });
348
+ }
349
+ _end(error) {
350
+ if (this._state === "ended") {
351
+ return;
352
+ }
353
+ this._error = error;
354
+ this._teardown();
355
+ this._setState("ended");
356
+ // If start() is still pending, it rejects on failure and resolves on hangup().
357
+ if (this._pendingStart !== undefined) {
358
+ if (error) {
359
+ this._pendingStart.reject(error);
360
+ }
361
+ else {
362
+ this._pendingStart.resolve();
363
+ }
364
+ this._pendingStart = undefined;
365
+ }
366
+ }
367
+ _teardown() {
368
+ // Close the signaling socket.
369
+ if (this._sock) {
370
+ // Don't fire close handlers for a socket we closed ourselves.
371
+ this._sock.onclose = null;
372
+ this._sock.close();
373
+ this._sock = undefined;
374
+ }
375
+ // Close the chat socket.
376
+ if (this._chatSock) {
377
+ this._chatSock.close();
378
+ this._chatSock = undefined;
379
+ }
380
+ this._chatReady = false;
381
+ this._pendingChatMessages = [];
382
+ // Close the peer connection.
383
+ if (this._peerConnection !== undefined) {
384
+ this._peerConnection.close();
385
+ this._peerConnection = undefined;
386
+ }
387
+ for (const track of this._localStream?.getTracks() ?? []) {
388
+ track.stop();
389
+ }
390
+ this._localStream = undefined;
391
+ this._remoteStream = undefined;
392
+ // Remove the audio element.
393
+ this._remoteAudio.srcObject = null;
394
+ this._remoteAudio.remove();
395
+ }
396
+ }
397
+ exports.Call = Call;
398
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/webrtc/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ export interface ConnectingTone {
2
+ start(): void;
3
+ stop(): void;
4
+ }
5
+ export declare class RingbackTone implements ConnectingTone {
6
+ private context;
7
+ private intervalId;
8
+ private readonly volume;
9
+ private readonly onSeconds;
10
+ private readonly periodSeconds;
11
+ private readonly startDelay;
12
+ start(): void;
13
+ stop(): void;
14
+ }
15
+ export declare class JingleTone implements ConnectingTone {
16
+ private context;
17
+ private masterGain;
18
+ private intervalId;
19
+ private running;
20
+ private pulseCount;
21
+ private nextBarStart;
22
+ private readonly volume;
23
+ private readonly bpm;
24
+ private readonly beatsPerBar;
25
+ private readonly startDelay;
26
+ start(): void;
27
+ private noteToFrequency;
28
+ stop(): void;
29
+ private playPulse;
30
+ private playNote;
31
+ }
32
+ export interface Tone {
33
+ play(): void;
34
+ }
35
+ export declare class LeavingTone implements Tone {
36
+ play(): void;
37
+ private playNote;
38
+ }