@gravity-rail/sdk 0.22.0 → 0.32.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 +57 -8
- package/dist/agui.d.cts +1 -1
- package/dist/agui.d.ts +1 -1
- package/dist/audio.d.cts +1 -1
- package/dist/audio.d.ts +1 -1
- package/dist/{client-C10qSd6b.d.ts → chat-interaction-BKdImgZ5.d.ts} +5604 -1531
- package/dist/{client-Ct0soeip.d.cts → chat-interaction-DLfC_h_P.d.cts} +5604 -1531
- package/dist/{chunk-3HAV5XUJ.js → chunk-HRUMZ46V.js} +1 -1
- package/dist/chunk-HRUMZ46V.js.map +1 -0
- package/dist/{chunk-WMA6YCAS.js → chunk-N446FGCT.js} +1230 -201
- package/dist/chunk-N446FGCT.js.map +1 -0
- package/dist/{chunk-7OLBLLV7.js → chunk-P2E6LU7I.js} +57 -7
- package/dist/chunk-P2E6LU7I.js.map +1 -0
- package/dist/helpers.cjs +54 -1
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +3 -2
- package/dist/helpers.d.ts +3 -2
- package/dist/helpers.js +11 -3
- package/dist/helpers.js.map +1 -1
- package/dist/index.cjs +2291 -148
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +509 -6
- package/dist/index.d.ts +509 -6
- package/dist/index.js +1032 -23
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +1320 -220
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +33 -49
- package/dist/internal.d.ts +33 -49
- package/dist/internal.js +73 -33
- package/dist/internal.js.map +1 -1
- package/dist/realtime.cjs +279 -14
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +169 -17
- package/dist/realtime.d.ts +169 -17
- package/dist/realtime.js +264 -13
- package/dist/realtime.js.map +1 -1
- package/dist/{revision-state-CCPTiW-i.d.cts → revision-state-Bsq5dKwi.d.cts} +236 -5
- package/dist/{revision-state-C6aM-PHu.d.ts → revision-state-CQTYcIRG.d.ts} +236 -5
- package/dist/schemas.cjs +3 -1
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +31 -13
- package/dist/schemas.d.ts +31 -13
- package/dist/schemas.js +4 -2
- package/dist/schemas.js.map +1 -1
- package/dist/{tasks-WH_VfzMv.d.cts → tasks-B-31JPuq.d.cts} +298 -114
- package/dist/{tasks-WH_VfzMv.d.ts → tasks-B-31JPuq.d.ts} +298 -114
- package/dist/types-0c6_NGU4.d.cts +90 -0
- package/dist/types-0c6_NGU4.d.ts +90 -0
- package/package.json +3 -3
- package/dist/chunk-3HAV5XUJ.js.map +0 -1
- package/dist/chunk-7OLBLLV7.js.map +0 -1
- package/dist/chunk-WMA6YCAS.js.map +0 -1
- package/dist/types-DkYyrvoC.d.cts +0 -19
- package/dist/types-DkYyrvoC.d.ts +0 -19
package/dist/realtime.cjs
CHANGED
|
@@ -20,14 +20,28 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/realtime/index.ts
|
|
21
21
|
var realtime_exports = {};
|
|
22
22
|
__export(realtime_exports, {
|
|
23
|
+
ACCOUNT_ACTIVITY_CHANNEL: () => ACCOUNT_ACTIVITY_CHANNEL,
|
|
24
|
+
ACCOUNT_PRESENCE_CHANNEL: () => ACCOUNT_PRESENCE_CHANNEL,
|
|
25
|
+
ACTIVITY_CHANNEL: () => ACTIVITY_CHANNEL,
|
|
26
|
+
ACTIVITY_MEMBER_CHANNEL: () => ACTIVITY_MEMBER_CHANNEL,
|
|
27
|
+
AccountRealtimeClient: () => AccountRealtimeClient,
|
|
23
28
|
OperatorSessionClient: () => OperatorSessionClient,
|
|
29
|
+
PRESENCE_CHANNEL: () => PRESENCE_CHANNEL,
|
|
30
|
+
RealtimeSocketClient: () => RealtimeSocketClient,
|
|
24
31
|
WorkspaceRealtimeClient: () => WorkspaceRealtimeClient,
|
|
32
|
+
buildAccountWsUrl: () => buildAccountWsUrl,
|
|
25
33
|
buildWorkspaceWsUrl: () => buildWorkspaceWsUrl,
|
|
34
|
+
initAccountSocket: () => initAccountSocket,
|
|
26
35
|
initWorkspaceSocket: () => initWorkspaceSocket,
|
|
36
|
+
isAccountSocketConnected: () => isAccountSocketConnected,
|
|
27
37
|
isActiveCallPhase: () => isActiveCallPhase,
|
|
38
|
+
isActivityInvalidation: () => isActivityInvalidation,
|
|
28
39
|
isWorkspaceSocketConnected: () => isWorkspaceSocketConnected,
|
|
40
|
+
onAccountSocketConnection: () => onAccountSocketConnection,
|
|
29
41
|
onWorkspaceSocketConnection: () => onWorkspaceSocketConnection,
|
|
30
|
-
|
|
42
|
+
subscribeAccountChannel: () => subscribeAccountChannel,
|
|
43
|
+
subscribeWorkspaceChannel: () => subscribeWorkspaceChannel,
|
|
44
|
+
workspaceChannel: () => workspaceChannel
|
|
31
45
|
});
|
|
32
46
|
module.exports = __toCommonJS(realtime_exports);
|
|
33
47
|
|
|
@@ -35,19 +49,37 @@ module.exports = __toCommonJS(realtime_exports);
|
|
|
35
49
|
function isActiveCallPhase(phase) {
|
|
36
50
|
return phase === "dialing" || phase === "live" || phase === "onHold";
|
|
37
51
|
}
|
|
52
|
+
var ACTIVITY_CHANNEL = "activity";
|
|
53
|
+
var ACTIVITY_MEMBER_CHANNEL = "activity:me";
|
|
54
|
+
var ACCOUNT_ACTIVITY_CHANNEL = "account:activity";
|
|
55
|
+
var ACCOUNT_PRESENCE_CHANNEL = "account:presence";
|
|
56
|
+
var PRESENCE_CHANNEL = "presence";
|
|
57
|
+
function isActivityInvalidation(event) {
|
|
58
|
+
if (event.type !== "invalidate") return false;
|
|
59
|
+
const data = event.data;
|
|
60
|
+
if (typeof data !== "object" || data === null) return false;
|
|
61
|
+
const scope = data.scope;
|
|
62
|
+
return scope === "workspace" || scope === "member" || scope === "account";
|
|
63
|
+
}
|
|
38
64
|
|
|
39
|
-
// src/realtime/
|
|
65
|
+
// src/realtime/socket-client.ts
|
|
40
66
|
var HEARTBEAT_INTERVAL_MS = 3e4;
|
|
41
67
|
var RECONNECT_DELAY_MS = 3e3;
|
|
42
68
|
var MAX_RECONNECT_ATTEMPTS = 5;
|
|
43
69
|
var CLOSE_DELAY_MS = 1e3;
|
|
70
|
+
var MAX_SUBSCRIBE_RETRY_DELAY_MS = 3e4;
|
|
44
71
|
function createSocketState() {
|
|
45
72
|
return {
|
|
46
73
|
ws: null,
|
|
47
74
|
connected: false,
|
|
48
75
|
connecting: false,
|
|
76
|
+
lastError: null,
|
|
49
77
|
listeners: /* @__PURE__ */ new Map(),
|
|
50
78
|
subscribedChannels: /* @__PURE__ */ new Set(),
|
|
79
|
+
subscriptionRevision: 0,
|
|
80
|
+
subscriptionRetryChannels: /* @__PURE__ */ new Set(),
|
|
81
|
+
subscriptionRetryAttempts: 0,
|
|
82
|
+
subscriptionRetryTimer: null,
|
|
51
83
|
reconnectAttempts: 0,
|
|
52
84
|
reconnectTimer: null,
|
|
53
85
|
heartbeatTimer: null,
|
|
@@ -55,12 +87,7 @@ function createSocketState() {
|
|
|
55
87
|
intentionalClose: false
|
|
56
88
|
};
|
|
57
89
|
}
|
|
58
|
-
|
|
59
|
-
const isSsl = session.apiUrl.startsWith("https");
|
|
60
|
-
const host = session.apiUrl.replace(/^https?:\/\//, "");
|
|
61
|
-
return `${isSsl ? "wss" : "ws"}://${host}/api/v2/w/${session.workspaceUuid}/ws/realtime`;
|
|
62
|
-
}
|
|
63
|
-
var WorkspaceRealtimeClient = class {
|
|
90
|
+
var RealtimeSocketClient = class {
|
|
64
91
|
session = null;
|
|
65
92
|
getSessionFn;
|
|
66
93
|
state = createSocketState();
|
|
@@ -75,6 +102,16 @@ var WorkspaceRealtimeClient = class {
|
|
|
75
102
|
}
|
|
76
103
|
}
|
|
77
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Whether replacing `previous` with `next` invalidates the open socket.
|
|
107
|
+
*
|
|
108
|
+
* The token always does; the rest is mount-specific — a workspace client
|
|
109
|
+
* changing workspace is a different socket, and an account client has no
|
|
110
|
+
* such axis.
|
|
111
|
+
*/
|
|
112
|
+
sessionRequiresReconnect(previous, next) {
|
|
113
|
+
return previous?.accessToken !== next.accessToken || previous?.apiUrl !== next.apiUrl;
|
|
114
|
+
}
|
|
78
115
|
resolveSession() {
|
|
79
116
|
return this.session ?? this.getSessionFn?.() ?? null;
|
|
80
117
|
}
|
|
@@ -89,8 +126,54 @@ var WorkspaceRealtimeClient = class {
|
|
|
89
126
|
this.state.closeTimer = null;
|
|
90
127
|
}
|
|
91
128
|
}
|
|
129
|
+
clearSubscriptionRetry(channel) {
|
|
130
|
+
if (channel) {
|
|
131
|
+
this.state.subscriptionRetryChannels.delete(channel);
|
|
132
|
+
} else {
|
|
133
|
+
this.state.subscriptionRetryChannels.clear();
|
|
134
|
+
}
|
|
135
|
+
if (this.state.subscriptionRetryChannels.size > 0) return;
|
|
136
|
+
if (this.state.subscriptionRetryTimer) {
|
|
137
|
+
clearTimeout(this.state.subscriptionRetryTimer);
|
|
138
|
+
this.state.subscriptionRetryTimer = null;
|
|
139
|
+
}
|
|
140
|
+
this.state.subscriptionRetryAttempts = 0;
|
|
141
|
+
}
|
|
142
|
+
scheduleSubscriptionRetry(channels) {
|
|
143
|
+
for (const channel of channels) {
|
|
144
|
+
if (this.state.listeners.has(channel) && !this.state.subscribedChannels.has(channel)) {
|
|
145
|
+
this.state.subscriptionRetryChannels.add(channel);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (this.state.subscriptionRetryChannels.size === 0 || this.state.subscriptionRetryTimer) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
this.state.subscriptionRetryAttempts += 1;
|
|
152
|
+
const delay = Math.min(
|
|
153
|
+
RECONNECT_DELAY_MS * this.state.subscriptionRetryAttempts,
|
|
154
|
+
MAX_SUBSCRIBE_RETRY_DELAY_MS
|
|
155
|
+
);
|
|
156
|
+
this.state.subscriptionRetryTimer = setTimeout(() => {
|
|
157
|
+
this.state.subscriptionRetryTimer = null;
|
|
158
|
+
const retryChannels = Array.from(this.state.subscriptionRetryChannels).filter(
|
|
159
|
+
(channel) => this.state.listeners.has(channel) && !this.state.subscribedChannels.has(channel)
|
|
160
|
+
);
|
|
161
|
+
for (const channel of this.state.subscriptionRetryChannels) {
|
|
162
|
+
if (!retryChannels.includes(channel)) {
|
|
163
|
+
this.state.subscriptionRetryChannels.delete(channel);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (retryChannels.length === 0) {
|
|
167
|
+
this.state.subscriptionRetryAttempts = 0;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (this.state.connected && this.state.ws?.readyState === WebSocket.OPEN) {
|
|
171
|
+
this.state.ws.send(JSON.stringify({ type: "subscribe", channels: retryChannels }));
|
|
172
|
+
}
|
|
173
|
+
}, delay);
|
|
174
|
+
}
|
|
92
175
|
setSession(session) {
|
|
93
|
-
const changed = this.
|
|
176
|
+
const changed = this.sessionRequiresReconnect(this.session, session);
|
|
94
177
|
this.session = session;
|
|
95
178
|
if (changed && this.state.ws) {
|
|
96
179
|
this.closeConnection();
|
|
@@ -117,6 +200,7 @@ var WorkspaceRealtimeClient = class {
|
|
|
117
200
|
if (channelListeners && channelListeners.size === 0) {
|
|
118
201
|
this.state.listeners.delete(channel);
|
|
119
202
|
this.state.subscribedChannels.delete(channel);
|
|
203
|
+
this.clearSubscriptionRetry(channel);
|
|
120
204
|
if (this.state.connected && this.state.ws?.readyState === WebSocket.OPEN) {
|
|
121
205
|
this.state.ws.send(JSON.stringify({ type: "unsubscribe", channels: [channel] }));
|
|
122
206
|
}
|
|
@@ -144,6 +228,44 @@ var WorkspaceRealtimeClient = class {
|
|
|
144
228
|
isConnected() {
|
|
145
229
|
return this.state.connected;
|
|
146
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Whether the server has acknowledged this channel subscription.
|
|
233
|
+
*
|
|
234
|
+
* This is stricter than having a local listener: it becomes true only after
|
|
235
|
+
* a `subscribed` frame, returns to false on disconnect or server-driven
|
|
236
|
+
* unsubscribe, and stays false while automatic subscribe retry is pending.
|
|
237
|
+
* Consumers that must order a command after subscription admission should
|
|
238
|
+
* observe {@link getSubscriptionRevision} and re-read this method.
|
|
239
|
+
*/
|
|
240
|
+
isSubscribed(channel) {
|
|
241
|
+
return this.state.subscribedChannels.has(channel);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Monotonic local revision of acknowledged subscription state.
|
|
245
|
+
*
|
|
246
|
+
* It increments when `subscribed` or `unsubscribed` changes the server-
|
|
247
|
+
* acknowledged set. It is not a protocol sequence number and resets with a
|
|
248
|
+
* new client instance; its purpose is external-store invalidation before a
|
|
249
|
+
* consumer calls {@link isSubscribed} again.
|
|
250
|
+
*/
|
|
251
|
+
getSubscriptionRevision() {
|
|
252
|
+
return this.state.subscriptionRevision;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* A socket is open or opening and has not yet said `protocol.init`.
|
|
256
|
+
*
|
|
257
|
+
* Real state, read off the state machine. Consumers used to report a
|
|
258
|
+
* literal `false` here and render "Available" over a socket that had never
|
|
259
|
+
* connected; a toggle that cannot distinguish "not live" from "cannot tell
|
|
260
|
+
* yet" is the shape of that bug.
|
|
261
|
+
*/
|
|
262
|
+
isConnecting() {
|
|
263
|
+
return this.state.connecting;
|
|
264
|
+
}
|
|
265
|
+
/** The last failure the socket gave up on, or null. See {@link SocketState.lastError}. */
|
|
266
|
+
getLastError() {
|
|
267
|
+
return this.state.lastError;
|
|
268
|
+
}
|
|
147
269
|
ensureConnection() {
|
|
148
270
|
const session = this.resolveSession();
|
|
149
271
|
if (!session) return;
|
|
@@ -152,17 +274,21 @@ var WorkspaceRealtimeClient = class {
|
|
|
152
274
|
this.clearCloseTimer();
|
|
153
275
|
this.state.connecting = true;
|
|
154
276
|
this.state.intentionalClose = false;
|
|
155
|
-
|
|
277
|
+
this.notifyConnectionListeners();
|
|
278
|
+
const ws = new WebSocket(this.buildUrl(session));
|
|
156
279
|
ws.onopen = () => {
|
|
157
280
|
ws.send(JSON.stringify({ type: "login", token: session.accessToken }));
|
|
158
281
|
};
|
|
159
282
|
ws.onmessage = (event) => {
|
|
283
|
+
if (this.state.ws !== null && this.state.ws !== ws) return;
|
|
160
284
|
try {
|
|
161
285
|
const msg = JSON.parse(String(event.data));
|
|
162
286
|
if (msg.type === "protocol.init" && !this.state.connected) {
|
|
163
287
|
this.state.connected = true;
|
|
288
|
+
this.readProtocolInit(msg);
|
|
164
289
|
this.state.connecting = false;
|
|
165
290
|
this.state.reconnectAttempts = 0;
|
|
291
|
+
this.state.lastError = null;
|
|
166
292
|
if (this.state.heartbeatTimer) clearInterval(this.state.heartbeatTimer);
|
|
167
293
|
this.state.heartbeatTimer = setInterval(() => {
|
|
168
294
|
if (this.state.ws?.readyState === WebSocket.OPEN) {
|
|
@@ -183,13 +309,40 @@ var WorkspaceRealtimeClient = class {
|
|
|
183
309
|
if (msg.type === "subscribed" && Array.isArray(msg.channels)) {
|
|
184
310
|
for (const ch of msg.channels) {
|
|
185
311
|
this.state.subscribedChannels.add(ch);
|
|
312
|
+
this.clearSubscriptionRetry(ch);
|
|
186
313
|
}
|
|
314
|
+
this.state.subscriptionRevision += 1;
|
|
315
|
+
this.notifyConnectionListeners();
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (msg.type === "subscribe_error" && Array.isArray(msg.errors)) {
|
|
319
|
+
const retryableChannels = [];
|
|
320
|
+
for (const rawError of msg.errors) {
|
|
321
|
+
if (!rawError || typeof rawError !== "object") continue;
|
|
322
|
+
const error = rawError;
|
|
323
|
+
if (typeof error.channel !== "string") continue;
|
|
324
|
+
if (error.retryable === true) {
|
|
325
|
+
retryableChannels.push(error.channel);
|
|
326
|
+
} else {
|
|
327
|
+
this.clearSubscriptionRetry(error.channel);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
this.scheduleSubscriptionRetry(retryableChannels);
|
|
187
331
|
return;
|
|
188
332
|
}
|
|
189
333
|
if (msg.type === "unsubscribed" && Array.isArray(msg.channels)) {
|
|
190
334
|
for (const ch of msg.channels) {
|
|
191
335
|
this.state.subscribedChannels.delete(ch);
|
|
192
336
|
}
|
|
337
|
+
this.state.subscriptionRevision += 1;
|
|
338
|
+
this.notifyConnectionListeners();
|
|
339
|
+
this.scheduleSubscriptionRetry(msg.channels);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
if (msg.type === "error") {
|
|
343
|
+
const message = msg.message;
|
|
344
|
+
this.state.lastError = typeof message === "string" && message ? message : "Realtime error";
|
|
345
|
+
this.notifyConnectionListeners();
|
|
193
346
|
return;
|
|
194
347
|
}
|
|
195
348
|
if (msg.type === "event" && msg.channel && msg.event) {
|
|
@@ -208,16 +361,22 @@ var WorkspaceRealtimeClient = class {
|
|
|
208
361
|
}
|
|
209
362
|
};
|
|
210
363
|
ws.onclose = () => {
|
|
364
|
+
if (this.state.ws !== null && this.state.ws !== ws) return;
|
|
211
365
|
this.state.connected = false;
|
|
212
366
|
this.state.connecting = false;
|
|
213
367
|
this.state.ws = null;
|
|
214
368
|
this.state.subscribedChannels.clear();
|
|
369
|
+
this.clearSubscriptionRetry();
|
|
215
370
|
if (this.state.heartbeatTimer) {
|
|
216
371
|
clearInterval(this.state.heartbeatTimer);
|
|
217
372
|
this.state.heartbeatTimer = null;
|
|
218
373
|
}
|
|
374
|
+
const willRetry = !this.state.intentionalClose && this.state.listeners.size > 0 && this.state.reconnectAttempts < MAX_RECONNECT_ATTEMPTS;
|
|
375
|
+
if (!willRetry && !this.state.intentionalClose && this.state.listeners.size > 0) {
|
|
376
|
+
this.state.lastError = "Realtime connection lost";
|
|
377
|
+
}
|
|
219
378
|
this.notifyConnectionListeners();
|
|
220
|
-
if (
|
|
379
|
+
if (willRetry) {
|
|
221
380
|
this.state.reconnectAttempts += 1;
|
|
222
381
|
this.state.reconnectTimer = setTimeout(() => {
|
|
223
382
|
this.ensureConnection();
|
|
@@ -242,11 +401,47 @@ var WorkspaceRealtimeClient = class {
|
|
|
242
401
|
this.state.ws?.close();
|
|
243
402
|
this.state.ws = null;
|
|
244
403
|
this.state.connected = false;
|
|
404
|
+
this.clearIdentity();
|
|
245
405
|
this.state.connecting = false;
|
|
246
406
|
this.state.subscribedChannels.clear();
|
|
407
|
+
this.clearSubscriptionRetry();
|
|
247
408
|
this.notifyConnectionListeners();
|
|
248
409
|
}
|
|
249
410
|
};
|
|
411
|
+
|
|
412
|
+
// src/realtime/workspace-client.ts
|
|
413
|
+
function buildWorkspaceWsUrl(session) {
|
|
414
|
+
const isSsl = session.apiUrl.startsWith("https");
|
|
415
|
+
const host = session.apiUrl.replace(/^https?:\/\//, "");
|
|
416
|
+
return `${isSsl ? "wss" : "ws"}://${host}/api/v2/w/${session.workspaceUuid}/ws/realtime`;
|
|
417
|
+
}
|
|
418
|
+
var WorkspaceRealtimeClient = class extends RealtimeSocketClient {
|
|
419
|
+
memberId = null;
|
|
420
|
+
buildUrl(session) {
|
|
421
|
+
return buildWorkspaceWsUrl(session);
|
|
422
|
+
}
|
|
423
|
+
readProtocolInit(msg) {
|
|
424
|
+
this.memberId = typeof msg.memberId === "number" ? msg.memberId : null;
|
|
425
|
+
}
|
|
426
|
+
clearIdentity() {
|
|
427
|
+
this.memberId = null;
|
|
428
|
+
}
|
|
429
|
+
sessionRequiresReconnect(previous, next) {
|
|
430
|
+
return super.sessionRequiresReconnect(previous, next) || previous?.workspaceUuid !== next.workspaceUuid;
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Member id the server authenticated this socket as, or null before
|
|
434
|
+
* `protocol.init` arrives.
|
|
435
|
+
*
|
|
436
|
+
* Channels whose Redis key is workspace-wide can carry events addressed to
|
|
437
|
+
* one member (presence acks, for example). Consumers compare the event's
|
|
438
|
+
* addressee against this so a reply meant for another operator cannot be
|
|
439
|
+
* applied locally.
|
|
440
|
+
*/
|
|
441
|
+
getMemberId() {
|
|
442
|
+
return this.memberId;
|
|
443
|
+
}
|
|
444
|
+
};
|
|
250
445
|
var defaultClient = new WorkspaceRealtimeClient();
|
|
251
446
|
function initWorkspaceSocket(session) {
|
|
252
447
|
defaultClient.setSession(session);
|
|
@@ -261,6 +456,59 @@ function isWorkspaceSocketConnected() {
|
|
|
261
456
|
return defaultClient.isConnected();
|
|
262
457
|
}
|
|
263
458
|
|
|
459
|
+
// src/realtime/account-client.ts
|
|
460
|
+
function buildAccountWsUrl(session) {
|
|
461
|
+
const isSsl = session.apiUrl.startsWith("https");
|
|
462
|
+
const host = session.apiUrl.replace(/^https?:\/\//, "");
|
|
463
|
+
return `${isSsl ? "wss" : "ws"}://${host}/api/v2/ws/realtime`;
|
|
464
|
+
}
|
|
465
|
+
function workspaceChannel(workspaceUuid, channel) {
|
|
466
|
+
return `w/${workspaceUuid}/${channel}`;
|
|
467
|
+
}
|
|
468
|
+
var AccountRealtimeClient = class extends RealtimeSocketClient {
|
|
469
|
+
accountUuid = null;
|
|
470
|
+
workspaceUuids = [];
|
|
471
|
+
buildUrl(session) {
|
|
472
|
+
return buildAccountWsUrl(session);
|
|
473
|
+
}
|
|
474
|
+
readProtocolInit(msg) {
|
|
475
|
+
this.accountUuid = typeof msg.accountUuid === "string" ? msg.accountUuid : null;
|
|
476
|
+
this.workspaceUuids = Array.isArray(msg.workspaceUuids) ? msg.workspaceUuids.filter((value) => typeof value === "string") : [];
|
|
477
|
+
}
|
|
478
|
+
clearIdentity() {
|
|
479
|
+
this.accountUuid = null;
|
|
480
|
+
this.workspaceUuids = [];
|
|
481
|
+
}
|
|
482
|
+
/** Account uuid the server authenticated this socket as, or null. */
|
|
483
|
+
getAccountUuid() {
|
|
484
|
+
return this.accountUuid;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Workspaces the server's grant map admitted at `protocol.init`.
|
|
488
|
+
*
|
|
489
|
+
* A **hint for rendering**, never an authorization decision: the server
|
|
490
|
+
* re-checks its own map on every subscribe, and refreshes it on a floor, so
|
|
491
|
+
* this snapshot can be stale in either direction. Use it to decide which
|
|
492
|
+
* panes are worth opening, not which data a viewer may see.
|
|
493
|
+
*/
|
|
494
|
+
getWorkspaceUuids() {
|
|
495
|
+
return this.workspaceUuids;
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
var defaultClient2 = new AccountRealtimeClient();
|
|
499
|
+
function initAccountSocket(session) {
|
|
500
|
+
defaultClient2.setSession(session);
|
|
501
|
+
}
|
|
502
|
+
function subscribeAccountChannel(channel, listener) {
|
|
503
|
+
return defaultClient2.subscribe(channel, listener);
|
|
504
|
+
}
|
|
505
|
+
function onAccountSocketConnection(listener) {
|
|
506
|
+
return defaultClient2.onConnection(listener);
|
|
507
|
+
}
|
|
508
|
+
function isAccountSocketConnected() {
|
|
509
|
+
return defaultClient2.isConnected();
|
|
510
|
+
}
|
|
511
|
+
|
|
264
512
|
// src/audio/pcm.ts
|
|
265
513
|
var SERVER_SAMPLE_RATE = 24e3;
|
|
266
514
|
var TARGET_SAMPLE_RATE = 24e3;
|
|
@@ -495,7 +743,7 @@ var OperatorSessionClient = class {
|
|
|
495
743
|
* microphone before sending so the operator's audio is flowing the instant
|
|
496
744
|
* the bridge registers.
|
|
497
745
|
*/
|
|
498
|
-
async answerCall(interactionId) {
|
|
746
|
+
async answerCall(interactionId, answerToken) {
|
|
499
747
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
500
748
|
throw new Error("Operator session WebSocket is not connected");
|
|
501
749
|
}
|
|
@@ -503,7 +751,10 @@ var OperatorSessionClient = class {
|
|
|
503
751
|
throw new Error("Operator session is not ready");
|
|
504
752
|
}
|
|
505
753
|
await this.startMicrophone();
|
|
506
|
-
this.sendCustom("operator.call.answer", {
|
|
754
|
+
this.sendCustom("operator.call.answer", {
|
|
755
|
+
interaction_id: interactionId,
|
|
756
|
+
answer_token: answerToken
|
|
757
|
+
});
|
|
507
758
|
}
|
|
508
759
|
/**
|
|
509
760
|
* Mute or unmute the operator's outbound microphone. Muting gates mic frames
|
|
@@ -668,13 +919,27 @@ var OperatorSessionClient = class {
|
|
|
668
919
|
};
|
|
669
920
|
// Annotate the CommonJS export names for ESM import in node:
|
|
670
921
|
0 && (module.exports = {
|
|
922
|
+
ACCOUNT_ACTIVITY_CHANNEL,
|
|
923
|
+
ACCOUNT_PRESENCE_CHANNEL,
|
|
924
|
+
ACTIVITY_CHANNEL,
|
|
925
|
+
ACTIVITY_MEMBER_CHANNEL,
|
|
926
|
+
AccountRealtimeClient,
|
|
671
927
|
OperatorSessionClient,
|
|
928
|
+
PRESENCE_CHANNEL,
|
|
929
|
+
RealtimeSocketClient,
|
|
672
930
|
WorkspaceRealtimeClient,
|
|
931
|
+
buildAccountWsUrl,
|
|
673
932
|
buildWorkspaceWsUrl,
|
|
933
|
+
initAccountSocket,
|
|
674
934
|
initWorkspaceSocket,
|
|
935
|
+
isAccountSocketConnected,
|
|
675
936
|
isActiveCallPhase,
|
|
937
|
+
isActivityInvalidation,
|
|
676
938
|
isWorkspaceSocketConnected,
|
|
939
|
+
onAccountSocketConnection,
|
|
677
940
|
onWorkspaceSocketConnection,
|
|
678
|
-
|
|
941
|
+
subscribeAccountChannel,
|
|
942
|
+
subscribeWorkspaceChannel,
|
|
943
|
+
workspaceChannel
|
|
679
944
|
});
|
|
680
945
|
//# sourceMappingURL=realtime.cjs.map
|