@meshagent/meshagent 0.37.1 → 0.38.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/CHANGELOG.md +6 -0
- package/dist/browser/agent.js +74 -10
- package/dist/browser/developer-client.js +3 -0
- package/dist/browser/helpers.d.ts +2 -2
- package/dist/browser/helpers.js +1 -1
- package/dist/browser/meshagent-client.d.ts +25 -0
- package/dist/browser/meshagent-client.js +65 -0
- package/dist/browser/messaging-client.d.ts +29 -16
- package/dist/browser/messaging-client.js +256 -154
- package/dist/browser/participant.d.ts +7 -2
- package/dist/browser/participant.js +9 -9
- package/dist/browser/protocol.d.ts +85 -28
- package/dist/browser/protocol.js +356 -119
- package/dist/browser/room-client.d.ts +165 -29
- package/dist/browser/room-client.js +1114 -74
- package/dist/browser/room-event.d.ts +11 -0
- package/dist/browser/room-event.js +21 -1
- package/dist/browser/room-server-client.d.ts +2 -0
- package/dist/browser/room-server-client.js +6 -0
- package/dist/browser/runtime.d.ts +1 -1
- package/dist/browser/runtime.js +3 -1
- package/dist/browser/secrets-client.js +6 -2
- package/dist/browser/storage-client.d.ts +1 -0
- package/dist/browser/storage-client.js +9 -0
- package/dist/browser/sync-client.d.ts +16 -14
- package/dist/browser/sync-client.js +195 -116
- package/dist/esm/agent.js +74 -10
- package/dist/esm/developer-client.js +3 -0
- package/dist/esm/helpers.d.ts +2 -2
- package/dist/esm/helpers.js +1 -1
- package/dist/esm/meshagent-client.d.ts +25 -0
- package/dist/esm/meshagent-client.js +65 -0
- package/dist/esm/messaging-client.d.ts +29 -16
- package/dist/esm/messaging-client.js +256 -154
- package/dist/esm/participant.d.ts +7 -2
- package/dist/esm/participant.js +9 -9
- package/dist/esm/protocol.d.ts +85 -28
- package/dist/esm/protocol.js +352 -118
- package/dist/esm/room-client.d.ts +165 -29
- package/dist/esm/room-client.js +1112 -73
- package/dist/esm/room-event.d.ts +11 -0
- package/dist/esm/room-event.js +19 -0
- package/dist/esm/room-server-client.d.ts +2 -0
- package/dist/esm/room-server-client.js +7 -1
- package/dist/esm/runtime.d.ts +1 -1
- package/dist/esm/runtime.js +1 -1
- package/dist/esm/secrets-client.js +6 -2
- package/dist/esm/storage-client.d.ts +1 -0
- package/dist/esm/storage-client.js +9 -0
- package/dist/esm/sync-client.d.ts +16 -14
- package/dist/esm/sync-client.js +196 -117
- package/dist/node/agent.js +74 -10
- package/dist/node/developer-client.js +3 -0
- package/dist/node/helpers.d.ts +2 -2
- package/dist/node/helpers.js +1 -1
- package/dist/node/meshagent-client.d.ts +25 -0
- package/dist/node/meshagent-client.js +65 -0
- package/dist/node/messaging-client.d.ts +29 -16
- package/dist/node/messaging-client.js +256 -154
- package/dist/node/participant.d.ts +7 -2
- package/dist/node/participant.js +9 -9
- package/dist/node/protocol.d.ts +85 -28
- package/dist/node/protocol.js +356 -119
- package/dist/node/room-client.d.ts +165 -29
- package/dist/node/room-client.js +1114 -74
- package/dist/node/room-event.d.ts +11 -0
- package/dist/node/room-event.js +21 -1
- package/dist/node/room-server-client.d.ts +2 -0
- package/dist/node/room-server-client.js +6 -0
- package/dist/node/runtime.d.ts +1 -1
- package/dist/node/runtime.js +3 -1
- package/dist/node/secrets-client.js +6 -2
- package/dist/node/storage-client.d.ts +1 -0
- package/dist/node/storage-client.js +9 -0
- package/dist/node/sync-client.d.ts +16 -14
- package/dist/node/sync-client.js +195 -116
- package/package.json +6 -3
|
@@ -1,35 +1,248 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RoomClient = void 0;
|
|
3
|
+
exports.RoomClient = exports.RoomProtocolProxy = void 0;
|
|
4
4
|
const completer_1 = require("./completer");
|
|
5
|
-
const
|
|
6
|
-
const participant_1 = require("./participant");
|
|
7
|
-
const stream_controller_1 = require("./stream-controller");
|
|
8
|
-
const sync_client_1 = require("./sync-client");
|
|
5
|
+
const database_client_1 = require("./database-client");
|
|
9
6
|
const developer_client_1 = require("./developer-client");
|
|
10
|
-
const
|
|
7
|
+
const event_emitter_1 = require("./event-emitter");
|
|
11
8
|
const messaging_client_1 = require("./messaging-client");
|
|
9
|
+
const memory_client_1 = require("./memory-client");
|
|
10
|
+
const participant_1 = require("./participant");
|
|
11
|
+
const protocol_1 = require("./protocol");
|
|
12
12
|
const queues_client_1 = require("./queues-client");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const response_1 = require("./response");
|
|
14
|
+
const room_event_1 = require("./room-event");
|
|
15
|
+
const room_server_client_1 = require("./room-server-client");
|
|
15
16
|
const secrets_client_1 = require("./secrets-client");
|
|
16
|
-
const containers_client_1 = require("./containers-client");
|
|
17
|
-
const memory_client_1 = require("./memory-client");
|
|
18
17
|
const services_client_1 = require("./services-client");
|
|
19
|
-
const
|
|
20
|
-
const
|
|
18
|
+
const storage_client_1 = require("./storage-client");
|
|
19
|
+
const stream_controller_1 = require("./stream-controller");
|
|
20
|
+
const sync_client_1 = require("./sync-client");
|
|
21
|
+
const utils_1 = require("./utils");
|
|
22
|
+
const agent_client_1 = require("./agent-client");
|
|
23
|
+
const containers_client_1 = require("./containers-client");
|
|
24
|
+
class ProtocolStartupFailure extends Error {
|
|
25
|
+
constructor({ kind, reason }) {
|
|
26
|
+
super(reason ?? kind);
|
|
27
|
+
this.name = "ProtocolStartupFailure";
|
|
28
|
+
this.kind = kind;
|
|
29
|
+
this.reason = reason;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
class RoomClientTerminalState {
|
|
33
|
+
constructor({ requestMessage, toolCallMessage, messageSendMessage, }) {
|
|
34
|
+
this.requestMessage = requestMessage;
|
|
35
|
+
this.toolCallMessage = toolCallMessage;
|
|
36
|
+
this.messageSendMessage = messageSendMessage;
|
|
37
|
+
}
|
|
38
|
+
requestError() {
|
|
39
|
+
return new room_server_client_1.RoomServerException(this.requestMessage);
|
|
40
|
+
}
|
|
41
|
+
toolCallError() {
|
|
42
|
+
return new room_server_client_1.RoomServerException(this.toolCallMessage);
|
|
43
|
+
}
|
|
44
|
+
messageSendError() {
|
|
45
|
+
return new room_server_client_1.RoomServerException(this.messageSendMessage);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
class RoomConnectionStatusException extends room_server_client_1.RoomServerException {
|
|
49
|
+
constructor({ statusCode, statusText, }) {
|
|
50
|
+
const normalizedStatusText = statusText?.trim();
|
|
51
|
+
super(normalizedStatusText == null || normalizedStatusText.length === 0
|
|
52
|
+
? `websocket connect failed with status ${statusCode}`
|
|
53
|
+
: `websocket connect failed with status ${statusCode}: ${normalizedStatusText}`);
|
|
54
|
+
this.name = "RoomConnectionStatusException";
|
|
55
|
+
this.statusCode = statusCode;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function normalizeCloseReason(reason) {
|
|
59
|
+
if (reason == null) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const normalized = reason.trim();
|
|
63
|
+
return normalized.length === 0 ? null : normalized;
|
|
64
|
+
}
|
|
65
|
+
function wrapRoomConnectionError(error) {
|
|
66
|
+
if (error instanceof room_server_client_1.RoomServerException) {
|
|
67
|
+
return error;
|
|
68
|
+
}
|
|
69
|
+
if (error instanceof protocol_1.ProtocolHandshakeException) {
|
|
70
|
+
return new RoomConnectionStatusException({
|
|
71
|
+
statusCode: error.statusCode,
|
|
72
|
+
statusText: error.statusText,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (error instanceof protocol_1.ProtocolCloseException) {
|
|
76
|
+
return new room_server_client_1.RoomServerException(normalizeCloseReason(error.reason) ?? `room connection closed with status ${error.closeCode}`);
|
|
77
|
+
}
|
|
78
|
+
return new room_server_client_1.RoomServerException(`room connection error: ${String(error)}`);
|
|
79
|
+
}
|
|
80
|
+
function nonRetryableConnectFailureReason(error) {
|
|
81
|
+
if (error instanceof RoomConnectionStatusException
|
|
82
|
+
&& (error.statusCode === 403 || error.statusCode === 404)) {
|
|
83
|
+
return error.message;
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
function roomClosedBeforeReadyError(protocol) {
|
|
88
|
+
return new room_server_client_1.RoomServerException(normalizeCloseReason(protocol.closeReason) ?? "room connection closed before request completed");
|
|
89
|
+
}
|
|
90
|
+
function getEnvironmentValue(name) {
|
|
91
|
+
if (typeof process === "undefined") {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
return process.env?.[name];
|
|
95
|
+
}
|
|
96
|
+
function websocketRoomUrlFromEnvironment(roomName) {
|
|
97
|
+
const configuredBaseUrl = getEnvironmentValue("MESHAGENT_ROOM_URL")
|
|
98
|
+
?? getEnvironmentValue("MESHAGENT_API_URL")
|
|
99
|
+
?? "wss://api.meshagent.com";
|
|
100
|
+
let baseUrl = configuredBaseUrl;
|
|
101
|
+
if (baseUrl.startsWith("https:")) {
|
|
102
|
+
baseUrl = `wss:${baseUrl.slice("https:".length)}`;
|
|
103
|
+
}
|
|
104
|
+
else if (baseUrl.startsWith("http:")) {
|
|
105
|
+
baseUrl = `ws:${baseUrl.slice("http:".length)}`;
|
|
106
|
+
}
|
|
107
|
+
return `${baseUrl}/rooms/${roomName}`;
|
|
108
|
+
}
|
|
109
|
+
function createProtocolFactoryFromEnvironment() {
|
|
110
|
+
const roomName = getEnvironmentValue("MESHAGENT_ROOM");
|
|
111
|
+
const token = getEnvironmentValue("MESHAGENT_TOKEN");
|
|
112
|
+
if (roomName == null || roomName.trim().length === 0 || token == null || token.trim().length === 0) {
|
|
113
|
+
throw new Error("protocolFactory must be configured or MESHAGENT_ROOM and MESHAGENT_TOKEN must be set in the environment");
|
|
114
|
+
}
|
|
115
|
+
return protocol_1.WebSocketClientProtocol.createFactory({
|
|
116
|
+
url: websocketRoomUrlFromEnvironment(roomName),
|
|
117
|
+
token,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
class RoomProtocolProxy {
|
|
121
|
+
constructor({ room }) {
|
|
122
|
+
this._handlers = new Map();
|
|
123
|
+
this._room = room;
|
|
124
|
+
}
|
|
125
|
+
_bind(protocol) {
|
|
126
|
+
for (const [type, handler] of this._handlers.entries()) {
|
|
127
|
+
if (protocol.getHandler(type) === handler) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
protocol.addHandler(type, handler);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
_unbind(protocol) {
|
|
134
|
+
for (const [type, handler] of this._handlers.entries()) {
|
|
135
|
+
const current = protocol.getHandler(type);
|
|
136
|
+
if (current === handler) {
|
|
137
|
+
protocol.removeHandler(type, handler);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
addHandler(type, handler) {
|
|
142
|
+
if (this._handlers.has(type)) {
|
|
143
|
+
throw new Error(`already registered handler for ${type}`);
|
|
144
|
+
}
|
|
145
|
+
this._handlers.set(type, handler);
|
|
146
|
+
this._bind(this._room._protocolInstance);
|
|
147
|
+
}
|
|
148
|
+
removeHandler(type, handler) {
|
|
149
|
+
const registered = this._handlers.get(type);
|
|
150
|
+
if (registered !== handler) {
|
|
151
|
+
throw new Error(`handler mismatch for ${type}`);
|
|
152
|
+
}
|
|
153
|
+
this._handlers.delete(type);
|
|
154
|
+
if (this._room._protocolInstance.getHandler(type) === handler) {
|
|
155
|
+
this._room._protocolInstance.removeHandler(type, handler);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
getHandler(type) {
|
|
159
|
+
return this._handlers.get(type);
|
|
160
|
+
}
|
|
161
|
+
async send(type, data, { id } = {}) {
|
|
162
|
+
if (this._room._entered && !this._room.isConnected && !this._room._allowDisconnectedRequests) {
|
|
163
|
+
throw this._room._disconnectedError({ baseMessage: "room connection is disconnected" });
|
|
164
|
+
}
|
|
165
|
+
await this._room._protocolInstance.send(type, data, id);
|
|
166
|
+
}
|
|
167
|
+
sendNowait(type, data, { id } = {}) {
|
|
168
|
+
if (this._room._entered && !this._room.isConnected && !this._room._allowDisconnectedRequests) {
|
|
169
|
+
throw this._room._disconnectedError({ baseMessage: "room connection is disconnected" });
|
|
170
|
+
}
|
|
171
|
+
return this._room._protocolInstance.sendNowait(type, data, { id });
|
|
172
|
+
}
|
|
173
|
+
getNextMessageId() {
|
|
174
|
+
if (this._room._entered && !this._room.isConnected && !this._room._allowDisconnectedRequests) {
|
|
175
|
+
throw this._room._disconnectedError({ baseMessage: "room connection is disconnected" });
|
|
176
|
+
}
|
|
177
|
+
return this._room._protocolInstance.getNextMessageId();
|
|
178
|
+
}
|
|
179
|
+
get done() {
|
|
180
|
+
return this._room.waitForClose();
|
|
181
|
+
}
|
|
182
|
+
async waitForClose() {
|
|
183
|
+
await this._room.waitForClose();
|
|
184
|
+
}
|
|
185
|
+
get closeKind() {
|
|
186
|
+
return this._room.closeKind;
|
|
187
|
+
}
|
|
188
|
+
get closeReason() {
|
|
189
|
+
return this._room.closeReason;
|
|
190
|
+
}
|
|
191
|
+
get isOpen() {
|
|
192
|
+
return this._room._protocolInstance.isOpen;
|
|
193
|
+
}
|
|
194
|
+
get isClosed() {
|
|
195
|
+
return this._room.isClosed;
|
|
196
|
+
}
|
|
197
|
+
get token() {
|
|
198
|
+
return this._room._protocolInstance.token;
|
|
199
|
+
}
|
|
200
|
+
get url() {
|
|
201
|
+
return this._room._protocolInstance.url;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.RoomProtocolProxy = RoomProtocolProxy;
|
|
21
205
|
class RoomClient {
|
|
22
|
-
constructor({
|
|
206
|
+
constructor({ protocolFactory = null, reconnectTimeout = null, } = {}) {
|
|
207
|
+
this._entered = false;
|
|
208
|
+
this._allowDisconnectedRequests = false;
|
|
209
|
+
this._eventsController = new stream_controller_1.StreamController();
|
|
210
|
+
this._eventEmitter = new event_emitter_1.EventEmitter();
|
|
23
211
|
this._pendingRequests = new Map();
|
|
212
|
+
this._toolCallStreams = new Map();
|
|
213
|
+
this._ignoredResponseLabels = new Map();
|
|
24
214
|
this._ready = new completer_1.Completer();
|
|
215
|
+
this._roomClosed = new completer_1.Completer();
|
|
216
|
+
this._connectionReady = new completer_1.Completer();
|
|
217
|
+
this._localParticipantReady = new completer_1.Completer();
|
|
218
|
+
this._connected = false;
|
|
219
|
+
this._closing = false;
|
|
25
220
|
this._localParticipant = null;
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
221
|
+
this._lifecycleTask = null;
|
|
222
|
+
this._terminalState = null;
|
|
223
|
+
this._closeKind = null;
|
|
224
|
+
this._closeReason = null;
|
|
225
|
+
this._terminalCallbacksInvoked = false;
|
|
226
|
+
this._roomName = null;
|
|
227
|
+
this._roomUrl = null;
|
|
228
|
+
this._sessionId = null;
|
|
229
|
+
this._handleRoomReadyBound = this._handleRoomReady.bind(this);
|
|
230
|
+
this._handleRoomStatusBound = this._handleRoomStatus.bind(this);
|
|
231
|
+
this._handleParticipantBound = this._handleParticipant.bind(this);
|
|
232
|
+
this._handleResponseBound = this._handleResponse.bind(this);
|
|
233
|
+
this._handleToolCallResponseChunkBound = this._handleToolCallResponseChunk.bind(this);
|
|
234
|
+
if (reconnectTimeout != null && reconnectTimeout < 0) {
|
|
235
|
+
throw new Error("reconnectTimeout must be null or non-negative");
|
|
236
|
+
}
|
|
237
|
+
this._protocolFactory = protocolFactory ?? createProtocolFactoryFromEnvironment();
|
|
238
|
+
this._reconnectTimeout = reconnectTimeout;
|
|
239
|
+
this._protocolInstance = this._protocolFactory();
|
|
240
|
+
this.protocol = new RoomProtocolProxy({ room: this });
|
|
241
|
+
this.protocol.addHandler("room_ready", this._handleRoomReadyBound);
|
|
242
|
+
this.protocol.addHandler("room.status", this._handleRoomStatusBound);
|
|
243
|
+
this.protocol.addHandler("connected", this._handleParticipantBound);
|
|
244
|
+
this.protocol.addHandler("__response__", this._handleResponseBound);
|
|
245
|
+
this.protocol.addHandler("room.tool_call_response_chunk", this._handleToolCallResponseChunkBound);
|
|
33
246
|
this.sync = new sync_client_1.SyncClient({ room: this });
|
|
34
247
|
this.storage = new storage_client_1.StorageClient({ room: this });
|
|
35
248
|
this.developer = new developer_client_1.DeveloperClient({ room: this });
|
|
@@ -48,33 +261,820 @@ class RoomClient {
|
|
|
48
261
|
get ready() {
|
|
49
262
|
return this._ready.fut;
|
|
50
263
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
this.sync.start({ onDone, onError });
|
|
54
|
-
await this.ready;
|
|
264
|
+
get isConnected() {
|
|
265
|
+
return this._connected;
|
|
55
266
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
267
|
+
get isClosed() {
|
|
268
|
+
return this._closing || this._terminalState != null || this._roomClosed.completed;
|
|
269
|
+
}
|
|
270
|
+
get isClosing() {
|
|
271
|
+
return this._closing;
|
|
272
|
+
}
|
|
273
|
+
get closeKind() {
|
|
274
|
+
return this._closeKind ?? this._protocolInstance.closeKind;
|
|
275
|
+
}
|
|
276
|
+
get closeReason() {
|
|
277
|
+
return this._closeReason ?? normalizeCloseReason(this._protocolInstance.closeReason);
|
|
278
|
+
}
|
|
279
|
+
get roomName() {
|
|
280
|
+
return this._roomName;
|
|
281
|
+
}
|
|
282
|
+
get roomUrl() {
|
|
283
|
+
return this._roomUrl;
|
|
284
|
+
}
|
|
285
|
+
get sessionId() {
|
|
286
|
+
return this._sessionId;
|
|
287
|
+
}
|
|
288
|
+
isActiveProtocol(protocol) {
|
|
289
|
+
return protocol === this._protocolInstance;
|
|
290
|
+
}
|
|
291
|
+
on(eventName, callback) {
|
|
292
|
+
this._eventEmitter.on(eventName, callback);
|
|
293
|
+
}
|
|
294
|
+
off(eventName, callback) {
|
|
295
|
+
this._eventEmitter.off(eventName, callback);
|
|
296
|
+
}
|
|
297
|
+
emit(event) {
|
|
298
|
+
this._eventsController.add(event);
|
|
299
|
+
this._eventEmitter.emit(event.name, event);
|
|
300
|
+
}
|
|
301
|
+
listen() {
|
|
302
|
+
return this._eventsController.stream;
|
|
303
|
+
}
|
|
304
|
+
async waitForClose() {
|
|
305
|
+
await this._roomClosed.fut;
|
|
306
|
+
}
|
|
307
|
+
async waitUntilConnected() {
|
|
308
|
+
while (!this._connected) {
|
|
309
|
+
this._raiseIfTerminal();
|
|
310
|
+
if (this._roomClosed.completed) {
|
|
311
|
+
this._raiseIfTerminal();
|
|
312
|
+
throw this._disconnectedError({
|
|
313
|
+
baseMessage: "room connection closed before reconnect completed",
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
61
317
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
318
|
+
}
|
|
319
|
+
async _waitUntilConnectedForMessages() {
|
|
320
|
+
while (!this._connected) {
|
|
321
|
+
this._raiseIfTerminalForMessages();
|
|
322
|
+
if (this._roomClosed.completed) {
|
|
323
|
+
this._raiseIfTerminalForMessages();
|
|
324
|
+
throw this._messageDisconnectedError({
|
|
325
|
+
baseMessage: "room connection closed before message send completed",
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
_markConnected() {
|
|
332
|
+
this._connected = true;
|
|
333
|
+
this._closeKind = null;
|
|
334
|
+
this._closeReason = null;
|
|
335
|
+
}
|
|
336
|
+
_markDisconnected({ reason, kind, }) {
|
|
337
|
+
this._connected = false;
|
|
338
|
+
this._closeKind = kind;
|
|
339
|
+
this._closeReason = normalizeCloseReason(reason);
|
|
340
|
+
this._ignoredResponseLabels.clear();
|
|
341
|
+
}
|
|
342
|
+
_completeRoomClosed() {
|
|
343
|
+
if (!this._roomClosed.completed) {
|
|
344
|
+
this._roomClosed.complete();
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
_invokeTerminalCallbacks({ useErrorCallback, error, }) {
|
|
348
|
+
if (this._terminalCallbacksInvoked) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
this._terminalCallbacksInvoked = true;
|
|
352
|
+
if (useErrorCallback) {
|
|
353
|
+
this._errorHandler?.(error);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
this._doneHandler?.();
|
|
357
|
+
}
|
|
358
|
+
_formatClosedMessage({ baseMessage, protocol, closeReason, }) {
|
|
359
|
+
const normalized = normalizeCloseReason(closeReason) ??
|
|
360
|
+
normalizeCloseReason((protocol ?? this._protocolInstance).closeReason);
|
|
361
|
+
if (normalized == null) {
|
|
362
|
+
return baseMessage;
|
|
363
|
+
}
|
|
364
|
+
return `${baseMessage}: ${normalized}`;
|
|
365
|
+
}
|
|
366
|
+
_connectionFailureReason(error) {
|
|
367
|
+
if (error instanceof room_server_client_1.RoomServerException) {
|
|
368
|
+
return normalizeCloseReason(error.message);
|
|
369
|
+
}
|
|
370
|
+
return normalizeCloseReason(String(error));
|
|
371
|
+
}
|
|
372
|
+
_protocolTerminalState({ protocol } = {}) {
|
|
373
|
+
return new RoomClientTerminalState({
|
|
374
|
+
requestMessage: this._formatClosedMessage({
|
|
375
|
+
baseMessage: "room connection closed before request completed",
|
|
376
|
+
protocol,
|
|
377
|
+
}),
|
|
378
|
+
toolCallMessage: this._formatClosedMessage({
|
|
379
|
+
baseMessage: "room connection closed before tool call completed",
|
|
380
|
+
protocol,
|
|
381
|
+
}),
|
|
382
|
+
messageSendMessage: this._formatClosedMessage({
|
|
383
|
+
baseMessage: "room connection closed before message send completed",
|
|
384
|
+
protocol,
|
|
385
|
+
}),
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
_clientClosedTerminalState() {
|
|
389
|
+
return new RoomClientTerminalState({
|
|
390
|
+
requestMessage: "room client was closed before request completed",
|
|
391
|
+
toolCallMessage: "room client was closed before tool call completed",
|
|
392
|
+
messageSendMessage: "room client was closed before message send completed",
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
_unexpectedCloseTerminalState({ closeReason, }) {
|
|
396
|
+
return new RoomClientTerminalState({
|
|
397
|
+
requestMessage: this._formatClosedMessage({
|
|
398
|
+
baseMessage: "room connection unexpectedly closed before request completed",
|
|
399
|
+
closeReason,
|
|
400
|
+
}),
|
|
401
|
+
toolCallMessage: this._formatClosedMessage({
|
|
402
|
+
baseMessage: "room connection unexpectedly closed before tool call completed",
|
|
403
|
+
closeReason,
|
|
404
|
+
}),
|
|
405
|
+
messageSendMessage: this._formatClosedMessage({
|
|
406
|
+
baseMessage: "room connection unexpectedly closed before message send completed",
|
|
407
|
+
closeReason,
|
|
408
|
+
}),
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
_setStartupTerminalState({ closeKind, closeReason, protocol, }) {
|
|
412
|
+
const normalizedCloseReason = normalizeCloseReason(closeReason);
|
|
413
|
+
this._closeKind = closeKind;
|
|
414
|
+
this._closeReason = normalizedCloseReason;
|
|
415
|
+
if (closeKind === protocol_1.ProtocolCloseKind.ERROR) {
|
|
416
|
+
this._setTerminalState({
|
|
417
|
+
state: this._unexpectedCloseTerminalState({ closeReason: normalizedCloseReason }),
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
else if (closeKind === protocol_1.ProtocolCloseKind.CLIENT) {
|
|
421
|
+
this._setTerminalState({ state: this._clientClosedTerminalState() });
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
this._setTerminalState({ state: this._protocolTerminalState({ protocol }) });
|
|
425
|
+
}
|
|
426
|
+
if (!this._ready.completed) {
|
|
427
|
+
this._ready.completeError(this._startupException({
|
|
428
|
+
closeKind,
|
|
429
|
+
closeReason: normalizedCloseReason,
|
|
430
|
+
protocol,
|
|
431
|
+
}));
|
|
432
|
+
}
|
|
433
|
+
this._completeRoomClosed();
|
|
434
|
+
}
|
|
435
|
+
_setTerminalState({ state }) {
|
|
436
|
+
if (this._terminalState == null) {
|
|
437
|
+
this._terminalState = state;
|
|
438
|
+
}
|
|
439
|
+
return this._terminalState;
|
|
440
|
+
}
|
|
441
|
+
_raiseIfTerminal() {
|
|
442
|
+
if (this._terminalState != null) {
|
|
443
|
+
throw this._terminalState.requestError();
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
_raiseIfTerminalForMessages() {
|
|
447
|
+
if (this._terminalState != null) {
|
|
448
|
+
throw this._terminalState.messageSendError();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
_disconnectedError({ baseMessage }) {
|
|
452
|
+
return new room_server_client_1.RoomServerException(this._formatClosedMessage({
|
|
453
|
+
baseMessage,
|
|
454
|
+
}));
|
|
455
|
+
}
|
|
456
|
+
_messageDisconnectedError({ baseMessage, }) {
|
|
457
|
+
return new room_server_client_1.RoomServerException(this._formatClosedMessage({
|
|
458
|
+
baseMessage,
|
|
459
|
+
}));
|
|
460
|
+
}
|
|
461
|
+
_startupException({ closeKind, closeReason, protocol, }) {
|
|
462
|
+
const baseMessage = closeKind === protocol_1.ProtocolCloseKind.ERROR
|
|
463
|
+
? "room connection unexpectedly closed before the room became ready"
|
|
464
|
+
: closeKind === protocol_1.ProtocolCloseKind.CLIENT
|
|
465
|
+
? "room client was closed before the room became ready"
|
|
466
|
+
: "room connection closed before the room became ready";
|
|
467
|
+
return new room_server_client_1.RoomServerException(this._formatClosedMessage({
|
|
468
|
+
baseMessage,
|
|
469
|
+
protocol,
|
|
470
|
+
closeReason,
|
|
471
|
+
}));
|
|
472
|
+
}
|
|
473
|
+
_finalizeInitialStartupRetryFailure({ retryResult, }) {
|
|
474
|
+
const closeKind = retryResult.closeKind ?? null;
|
|
475
|
+
if (closeKind == null) {
|
|
476
|
+
throw new Error("initial startup retry failure requires a close kind");
|
|
477
|
+
}
|
|
478
|
+
this._setStartupTerminalState({
|
|
479
|
+
closeKind,
|
|
480
|
+
closeReason: retryResult.closeReason ?? null,
|
|
481
|
+
protocol: this._protocolInstance,
|
|
482
|
+
});
|
|
483
|
+
throw this._startupException({
|
|
484
|
+
closeKind,
|
|
485
|
+
closeReason: retryResult.closeReason ?? null,
|
|
486
|
+
protocol: this._protocolInstance,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
_coerceMessageSendError(error) {
|
|
490
|
+
if (this._terminalState == null) {
|
|
491
|
+
return error;
|
|
492
|
+
}
|
|
493
|
+
if (error.message === this._terminalState.requestMessage ||
|
|
494
|
+
error.message === this._terminalState.toolCallMessage) {
|
|
495
|
+
return this._terminalState.messageSendError();
|
|
496
|
+
}
|
|
497
|
+
return error;
|
|
498
|
+
}
|
|
499
|
+
_messageStopError() {
|
|
500
|
+
if (this._closing && this._terminalState != null) {
|
|
501
|
+
return this._terminalState.messageSendError();
|
|
502
|
+
}
|
|
503
|
+
return new room_server_client_1.RoomServerException("Cannot send messages because messaging has been stopped");
|
|
504
|
+
}
|
|
505
|
+
_failPendingRequests(error) {
|
|
506
|
+
if (this._pendingRequests.size === 0) {
|
|
507
|
+
return;
|
|
66
508
|
}
|
|
509
|
+
const pending = [...this._pendingRequests.values()];
|
|
510
|
+
this._pendingRequests.clear();
|
|
511
|
+
for (const request of pending) {
|
|
512
|
+
if (!request.completed) {
|
|
513
|
+
request.completeError(error);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
async _failToolCallStreams({ error, }) {
|
|
518
|
+
if (this._toolCallStreams.size === 0) {
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
const streams = [...this._toolCallStreams.values()];
|
|
67
522
|
this._toolCallStreams.clear();
|
|
68
|
-
|
|
523
|
+
for (const stream of streams) {
|
|
524
|
+
stream.add(new response_1.ErrorContent({ text: error.message }));
|
|
525
|
+
stream.close();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
async _failPendingWork({ state, }) {
|
|
529
|
+
this._failPendingRequests(state.requestError());
|
|
530
|
+
await this._failToolCallStreams({ error: state.toolCallError() });
|
|
531
|
+
}
|
|
532
|
+
async _openProtocol({ initial }) {
|
|
533
|
+
const protocol = this._protocolInstance;
|
|
534
|
+
this._connectionReady = new completer_1.Completer();
|
|
535
|
+
this._localParticipantReady = new completer_1.Completer();
|
|
536
|
+
protocol.start({
|
|
537
|
+
onDone: () => {
|
|
538
|
+
const error = roomClosedBeforeReadyError(protocol);
|
|
539
|
+
if (!this._connectionReady.completed) {
|
|
540
|
+
this._connectionReady.completeError(error);
|
|
541
|
+
}
|
|
542
|
+
if (!this._localParticipantReady.completed) {
|
|
543
|
+
this._localParticipantReady.completeError(error);
|
|
544
|
+
}
|
|
545
|
+
if (!initial && !this._ready.completed) {
|
|
546
|
+
this._ready.completeError(error);
|
|
547
|
+
}
|
|
548
|
+
},
|
|
549
|
+
onError: (error) => {
|
|
550
|
+
const wrapped = wrapRoomConnectionError(error);
|
|
551
|
+
if (!this._connectionReady.completed) {
|
|
552
|
+
this._connectionReady.completeError(wrapped);
|
|
553
|
+
}
|
|
554
|
+
if (!this._localParticipantReady.completed) {
|
|
555
|
+
this._localParticipantReady.completeError(wrapped);
|
|
556
|
+
}
|
|
557
|
+
if (!initial && !this._ready.completed) {
|
|
558
|
+
this._ready.completeError(wrapped);
|
|
559
|
+
}
|
|
560
|
+
},
|
|
561
|
+
});
|
|
562
|
+
try {
|
|
563
|
+
await Promise.all([this._connectionReady.fut, this._localParticipantReady.fut]);
|
|
564
|
+
}
|
|
565
|
+
catch (error) {
|
|
566
|
+
const kind = protocol.closeKind ?? protocol_1.ProtocolCloseKind.ERROR;
|
|
567
|
+
if (!initial && kind !== protocol_1.ProtocolCloseKind.ERROR) {
|
|
568
|
+
throw new ProtocolStartupFailure({
|
|
569
|
+
kind,
|
|
570
|
+
reason: normalizeCloseReason(protocol.closeReason),
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
throw error;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
async start({ onDone, onError, } = {}) {
|
|
577
|
+
if (this._entered) {
|
|
578
|
+
throw new room_server_client_1.RoomServerException("room client already started");
|
|
579
|
+
}
|
|
580
|
+
this._doneHandler = onDone;
|
|
581
|
+
this._errorHandler = onError;
|
|
582
|
+
try {
|
|
583
|
+
try {
|
|
584
|
+
await this._openProtocol({ initial: true });
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
if (error instanceof ProtocolStartupFailure) {
|
|
588
|
+
if (error.kind !== protocol_1.ProtocolCloseKind.ERROR || this._reconnectTimeout === 0) {
|
|
589
|
+
this._setStartupTerminalState({
|
|
590
|
+
closeKind: error.kind,
|
|
591
|
+
closeReason: error.reason,
|
|
592
|
+
protocol: this._protocolInstance,
|
|
593
|
+
});
|
|
594
|
+
throw this._startupException({
|
|
595
|
+
closeKind: error.kind,
|
|
596
|
+
closeReason: error.reason,
|
|
597
|
+
protocol: this._protocolInstance,
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
await this._closeProtocol(this._protocolInstance);
|
|
601
|
+
const retryResult = await this._retryProtocolConnection({
|
|
602
|
+
disconnectReason: error.reason,
|
|
603
|
+
protocolFactoryFailureLogMessage: "unable to create replacement room protocol during initial startup",
|
|
604
|
+
attemptFailureLogMessage: "room startup attempt failed",
|
|
605
|
+
attempt: this._attemptInitialProtocolStartup.bind(this),
|
|
606
|
+
});
|
|
607
|
+
if (!retryResult.connected) {
|
|
608
|
+
this._finalizeInitialStartupRetryFailure({ retryResult });
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
const nonRetryableCloseReason = nonRetryableConnectFailureReason(error);
|
|
613
|
+
if (nonRetryableCloseReason != null) {
|
|
614
|
+
this._finalizeInitialStartupRetryFailure({
|
|
615
|
+
retryResult: {
|
|
616
|
+
connected: false,
|
|
617
|
+
closeKind: protocol_1.ProtocolCloseKind.ERROR,
|
|
618
|
+
closeReason: nonRetryableCloseReason,
|
|
619
|
+
},
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
const closeKind = this._protocolInstance.closeKind;
|
|
623
|
+
const protocolCloseReason = normalizeCloseReason(this._protocolInstance.closeReason);
|
|
624
|
+
if (closeKind != null && closeKind !== protocol_1.ProtocolCloseKind.ERROR) {
|
|
625
|
+
this._setStartupTerminalState({
|
|
626
|
+
closeKind,
|
|
627
|
+
closeReason: protocolCloseReason,
|
|
628
|
+
protocol: this._protocolInstance,
|
|
629
|
+
});
|
|
630
|
+
throw this._startupException({
|
|
631
|
+
closeKind,
|
|
632
|
+
closeReason: protocolCloseReason,
|
|
633
|
+
protocol: this._protocolInstance,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
const closeReason = this._connectionFailureReason(error);
|
|
637
|
+
if (this._reconnectTimeout === 0) {
|
|
638
|
+
this._setStartupTerminalState({
|
|
639
|
+
closeKind: protocol_1.ProtocolCloseKind.ERROR,
|
|
640
|
+
closeReason,
|
|
641
|
+
protocol: this._protocolInstance,
|
|
642
|
+
});
|
|
643
|
+
throw this._startupException({
|
|
644
|
+
closeKind: protocol_1.ProtocolCloseKind.ERROR,
|
|
645
|
+
closeReason,
|
|
646
|
+
protocol: this._protocolInstance,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
console.debug("room startup attempt failed", error);
|
|
650
|
+
await this._closeProtocol(this._protocolInstance);
|
|
651
|
+
const retryResult = await this._retryProtocolConnection({
|
|
652
|
+
disconnectReason: closeReason,
|
|
653
|
+
protocolFactoryFailureLogMessage: "unable to create replacement room protocol during initial startup",
|
|
654
|
+
attemptFailureLogMessage: "room startup attempt failed",
|
|
655
|
+
attempt: this._attemptInitialProtocolStartup.bind(this),
|
|
656
|
+
});
|
|
657
|
+
if (!retryResult.connected) {
|
|
658
|
+
this._finalizeInitialStartupRetryFailure({ retryResult });
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
this.sync.start();
|
|
663
|
+
this.messaging.start();
|
|
664
|
+
this._entered = true;
|
|
665
|
+
this._markConnected();
|
|
666
|
+
this.messaging._onRoomReconnect();
|
|
667
|
+
this._lifecycleTask = this._connectionLifecycle();
|
|
668
|
+
}
|
|
669
|
+
catch (error) {
|
|
670
|
+
this.sync.dispose();
|
|
671
|
+
void this.messaging.stop();
|
|
672
|
+
this._protocolInstance.dispose();
|
|
673
|
+
throw error;
|
|
674
|
+
}
|
|
675
|
+
await this.ready;
|
|
676
|
+
}
|
|
677
|
+
async _completeReconnect() {
|
|
678
|
+
await this._openProtocol({ initial: false });
|
|
679
|
+
this._allowDisconnectedRequests = true;
|
|
680
|
+
try {
|
|
681
|
+
this._resendLocalAttributesNowait();
|
|
682
|
+
await this.sync._onRoomReconnect();
|
|
683
|
+
this.messaging._onRoomReconnect();
|
|
684
|
+
this._markConnected();
|
|
685
|
+
}
|
|
686
|
+
finally {
|
|
687
|
+
this._allowDisconnectedRequests = false;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
_replaceProtocol(nextProtocol) {
|
|
691
|
+
const currentProtocol = this._protocolInstance;
|
|
692
|
+
this.protocol._unbind(currentProtocol);
|
|
693
|
+
this._protocolInstance = nextProtocol;
|
|
694
|
+
this.protocol._bind(nextProtocol);
|
|
695
|
+
}
|
|
696
|
+
_remainingReconnectTimeout(deadline) {
|
|
697
|
+
if (deadline == null) {
|
|
698
|
+
return null;
|
|
699
|
+
}
|
|
700
|
+
const remaining = deadline - Date.now();
|
|
701
|
+
return remaining <= 0 ? 0 : remaining;
|
|
702
|
+
}
|
|
703
|
+
async _attemptInitialProtocolStartup({ protocol, remaining, }) {
|
|
704
|
+
void protocol;
|
|
705
|
+
if (remaining == null) {
|
|
706
|
+
await this._openProtocol({ initial: false });
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
await Promise.race([
|
|
710
|
+
this._openProtocol({ initial: false }),
|
|
711
|
+
new Promise((_resolve, reject) => {
|
|
712
|
+
setTimeout(() => reject(new Error("timeout")), remaining);
|
|
713
|
+
}),
|
|
714
|
+
]);
|
|
715
|
+
}
|
|
716
|
+
async _attemptReconnect({ protocol, remaining, }) {
|
|
717
|
+
try {
|
|
718
|
+
if (remaining == null) {
|
|
719
|
+
await this._completeReconnect();
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
await Promise.race([
|
|
723
|
+
this._completeReconnect(),
|
|
724
|
+
new Promise((_resolve, reject) => {
|
|
725
|
+
setTimeout(() => reject(new Error("timeout")), remaining);
|
|
726
|
+
}),
|
|
727
|
+
]);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
catch (error) {
|
|
731
|
+
if (error instanceof ProtocolStartupFailure) {
|
|
732
|
+
throw error;
|
|
733
|
+
}
|
|
734
|
+
if (error instanceof Error && error.message === "timeout") {
|
|
735
|
+
this._allowDisconnectedRequests = false;
|
|
736
|
+
await this.sync._onRoomDisconnect();
|
|
737
|
+
this.messaging._onRoomDisconnect({ reason: normalizeCloseReason(protocol.closeReason) });
|
|
738
|
+
throw error;
|
|
739
|
+
}
|
|
740
|
+
this._allowDisconnectedRequests = false;
|
|
741
|
+
await this.sync._onRoomDisconnect();
|
|
742
|
+
this.messaging._onRoomDisconnect({ reason: normalizeCloseReason(protocol.closeReason) });
|
|
743
|
+
throw error;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
_formatDuration(milliseconds) {
|
|
747
|
+
if (milliseconds % 1000 === 0) {
|
|
748
|
+
return `${milliseconds / 1000}s`;
|
|
749
|
+
}
|
|
750
|
+
return `${milliseconds / 1000}s`;
|
|
751
|
+
}
|
|
752
|
+
_reconnectTimeoutReason({ disconnectReason, }) {
|
|
753
|
+
if (this._reconnectTimeout == null) {
|
|
754
|
+
throw new Error("reconnect timeout reason requires a configured timeout");
|
|
755
|
+
}
|
|
756
|
+
const timeoutDisplay = this._formatDuration(this._reconnectTimeout);
|
|
757
|
+
if (disconnectReason == null) {
|
|
758
|
+
return `room reconnect timed out after ${timeoutDisplay}`;
|
|
759
|
+
}
|
|
760
|
+
return `room reconnect timed out after ${timeoutDisplay} (${disconnectReason})`;
|
|
761
|
+
}
|
|
762
|
+
_timedOutRetryResult({ disconnectReason, }) {
|
|
763
|
+
if (this._reconnectTimeout == null) {
|
|
764
|
+
throw new Error("timed out retry result requires a configured timeout");
|
|
765
|
+
}
|
|
766
|
+
return {
|
|
767
|
+
connected: false,
|
|
768
|
+
closeKind: protocol_1.ProtocolCloseKind.ERROR,
|
|
769
|
+
closeReason: this._reconnectTimeoutReason({ disconnectReason }),
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
async _closeAfterUnexpectedDisconnect({ closeReason, }) {
|
|
773
|
+
const normalized = normalizeCloseReason(closeReason);
|
|
774
|
+
const state = this._unexpectedCloseTerminalState({ closeReason: normalized });
|
|
775
|
+
this._closeKind = protocol_1.ProtocolCloseKind.ERROR;
|
|
776
|
+
this._closeReason = normalized;
|
|
777
|
+
this._setTerminalState({ state });
|
|
778
|
+
this._completeRoomClosed();
|
|
779
|
+
this._invokeTerminalCallbacks({
|
|
780
|
+
useErrorCallback: true,
|
|
781
|
+
error: state.requestError(),
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
async _closeProtocol(protocol) {
|
|
785
|
+
protocol.dispose();
|
|
786
|
+
await protocol.waitForClose();
|
|
787
|
+
}
|
|
788
|
+
async _retryProtocolConnection({ disconnectReason, protocolFactoryFailureLogMessage, attemptFailureLogMessage, attempt, }) {
|
|
789
|
+
let failureReason = normalizeCloseReason(disconnectReason);
|
|
790
|
+
const recordFailureReason = (reason) => {
|
|
791
|
+
const normalizedReason = normalizeCloseReason(reason);
|
|
792
|
+
if (failureReason == null && normalizedReason != null) {
|
|
793
|
+
failureReason = normalizedReason;
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
const deadline = this._reconnectTimeout == null ? null : Date.now() + this._reconnectTimeout;
|
|
797
|
+
let firstAttempt = true;
|
|
798
|
+
while (!this._closing) {
|
|
799
|
+
if (firstAttempt) {
|
|
800
|
+
firstAttempt = false;
|
|
801
|
+
if (this._reconnectTimeout == null) {
|
|
802
|
+
await new Promise((resolve) => setTimeout(resolve, RoomClient.RECONNECT_RETRY_INTERVAL_MS));
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
const remaining = this._remainingReconnectTimeout(deadline);
|
|
807
|
+
if (remaining != null && remaining === 0) {
|
|
808
|
+
return this._timedOutRetryResult({ disconnectReason: failureReason });
|
|
809
|
+
}
|
|
810
|
+
const delay = remaining == null
|
|
811
|
+
? RoomClient.RECONNECT_RETRY_INTERVAL_MS
|
|
812
|
+
: Math.min(remaining, RoomClient.RECONNECT_RETRY_INTERVAL_MS);
|
|
813
|
+
if (delay > 0) {
|
|
814
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
const remaining = this._remainingReconnectTimeout(deadline);
|
|
818
|
+
if (remaining != null && remaining === 0) {
|
|
819
|
+
return this._timedOutRetryResult({ disconnectReason: failureReason });
|
|
820
|
+
}
|
|
821
|
+
let nextProtocol;
|
|
822
|
+
try {
|
|
823
|
+
nextProtocol = this._protocolFactory();
|
|
824
|
+
}
|
|
825
|
+
catch (error) {
|
|
826
|
+
if (error instanceof protocol_1.ProtocolReconnectUnsupportedException) {
|
|
827
|
+
return {
|
|
828
|
+
connected: false,
|
|
829
|
+
closeKind: protocol_1.ProtocolCloseKind.ERROR,
|
|
830
|
+
closeReason: failureReason,
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
recordFailureReason(String(error));
|
|
834
|
+
console.debug(protocolFactoryFailureLogMessage, error);
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
this._replaceProtocol(nextProtocol);
|
|
838
|
+
try {
|
|
839
|
+
await attempt({ protocol: nextProtocol, remaining });
|
|
840
|
+
}
|
|
841
|
+
catch (error) {
|
|
842
|
+
if (error instanceof Error && error.message === "timeout") {
|
|
843
|
+
recordFailureReason(normalizeCloseReason(nextProtocol.closeReason));
|
|
844
|
+
await this._closeProtocol(nextProtocol);
|
|
845
|
+
return this._timedOutRetryResult({ disconnectReason: failureReason });
|
|
846
|
+
}
|
|
847
|
+
if (error instanceof ProtocolStartupFailure) {
|
|
848
|
+
recordFailureReason(error.reason);
|
|
849
|
+
await this._closeProtocol(nextProtocol);
|
|
850
|
+
if (error.kind !== protocol_1.ProtocolCloseKind.ERROR) {
|
|
851
|
+
return {
|
|
852
|
+
connected: false,
|
|
853
|
+
closeKind: error.kind,
|
|
854
|
+
closeReason: error.reason,
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
859
|
+
const nonRetryableCloseReason = nonRetryableConnectFailureReason(error);
|
|
860
|
+
if (nonRetryableCloseReason != null) {
|
|
861
|
+
await this._closeProtocol(nextProtocol);
|
|
862
|
+
return {
|
|
863
|
+
connected: false,
|
|
864
|
+
closeKind: protocol_1.ProtocolCloseKind.ERROR,
|
|
865
|
+
closeReason: nonRetryableCloseReason,
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
recordFailureReason(this._connectionFailureReason(error));
|
|
869
|
+
console.debug(attemptFailureLogMessage, error);
|
|
870
|
+
await this._closeProtocol(nextProtocol);
|
|
871
|
+
continue;
|
|
872
|
+
}
|
|
873
|
+
return { connected: true };
|
|
874
|
+
}
|
|
875
|
+
return {
|
|
876
|
+
connected: false,
|
|
877
|
+
closeKind: protocol_1.ProtocolCloseKind.CLIENT,
|
|
878
|
+
closeReason: this.closeReason,
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
async _reconnect({ disconnectReason, }) {
|
|
882
|
+
const retryResult = await this._retryProtocolConnection({
|
|
883
|
+
disconnectReason,
|
|
884
|
+
protocolFactoryFailureLogMessage: "unable to create replacement room protocol",
|
|
885
|
+
attemptFailureLogMessage: "room reconnect attempt failed",
|
|
886
|
+
attempt: this._attemptReconnect.bind(this),
|
|
887
|
+
});
|
|
888
|
+
if (retryResult.connected) {
|
|
889
|
+
this._emitStatus({
|
|
890
|
+
status: "reconnected",
|
|
891
|
+
message: "room connection restored",
|
|
892
|
+
});
|
|
893
|
+
return true;
|
|
894
|
+
}
|
|
895
|
+
const closeKind = retryResult.closeKind ?? null;
|
|
896
|
+
if (closeKind === protocol_1.ProtocolCloseKind.ERROR) {
|
|
897
|
+
const closeReason = retryResult.closeReason ?? null;
|
|
898
|
+
if (closeReason != null && closeReason.startsWith("room reconnect timed out after")) {
|
|
899
|
+
console.warn(`${closeReason}; closing room client`);
|
|
900
|
+
}
|
|
901
|
+
await this._closeAfterUnexpectedDisconnect({ closeReason });
|
|
902
|
+
return false;
|
|
903
|
+
}
|
|
904
|
+
if (closeKind == null) {
|
|
905
|
+
throw new Error("reconnect failure requires a close kind");
|
|
906
|
+
}
|
|
907
|
+
const state = this._protocolTerminalState({ protocol: this._protocolInstance });
|
|
908
|
+
this._setTerminalState({ state });
|
|
909
|
+
this._closeKind = closeKind;
|
|
910
|
+
this._closeReason = normalizeCloseReason(retryResult.closeReason ?? null);
|
|
911
|
+
this._completeRoomClosed();
|
|
912
|
+
this._invokeTerminalCallbacks({ useErrorCallback: false });
|
|
913
|
+
return false;
|
|
914
|
+
}
|
|
915
|
+
async _connectionLifecycle() {
|
|
916
|
+
while (true) {
|
|
917
|
+
const protocol = this._protocolInstance;
|
|
918
|
+
await protocol.done;
|
|
919
|
+
const closeKind = protocol.closeKind ?? protocol_1.ProtocolCloseKind.ERROR;
|
|
920
|
+
const closeReason = normalizeCloseReason(protocol.closeReason);
|
|
921
|
+
const state = this._protocolTerminalState({ protocol });
|
|
922
|
+
if (this._closing) {
|
|
923
|
+
this._completeRoomClosed();
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
if (closeKind !== protocol_1.ProtocolCloseKind.ERROR) {
|
|
927
|
+
this._setTerminalState({ state });
|
|
928
|
+
}
|
|
929
|
+
this._markDisconnected({ reason: closeReason, kind: closeKind });
|
|
930
|
+
this._emitStatus({
|
|
931
|
+
status: "disconnected",
|
|
932
|
+
message: closeReason ?? "room connection lost",
|
|
933
|
+
});
|
|
934
|
+
await this.sync._onRoomDisconnect();
|
|
935
|
+
this.messaging._onRoomDisconnect({ reason: closeReason });
|
|
936
|
+
await this._failPendingWork({ state });
|
|
937
|
+
await this._closeProtocol(protocol);
|
|
938
|
+
if (closeKind === protocol_1.ProtocolCloseKind.ERROR) {
|
|
939
|
+
if (this._reconnectTimeout === 0) {
|
|
940
|
+
if (closeReason == null) {
|
|
941
|
+
console.warn("room connection lost; automatic reconnect disabled");
|
|
942
|
+
}
|
|
943
|
+
else {
|
|
944
|
+
console.warn(`room connection lost (${closeReason}); automatic reconnect disabled`);
|
|
945
|
+
}
|
|
946
|
+
await this._closeAfterUnexpectedDisconnect({ closeReason });
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
if (closeReason == null) {
|
|
950
|
+
console.warn("room connection lost; automatically attempting to reconnect");
|
|
951
|
+
}
|
|
952
|
+
else {
|
|
953
|
+
console.warn(`room connection lost (${closeReason}); automatically attempting to reconnect`);
|
|
954
|
+
}
|
|
955
|
+
if (await this._reconnect({ disconnectReason: closeReason })) {
|
|
956
|
+
continue;
|
|
957
|
+
}
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
this._closeKind = closeKind;
|
|
961
|
+
this._closeReason = closeReason;
|
|
962
|
+
this._completeRoomClosed();
|
|
963
|
+
this._invokeTerminalCallbacks({ useErrorCallback: false });
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
dispose() {
|
|
968
|
+
this._closing = true;
|
|
969
|
+
this._markDisconnected({
|
|
970
|
+
reason: this.closeReason,
|
|
971
|
+
kind: this.closeKind ?? protocol_1.ProtocolCloseKind.CLIENT,
|
|
972
|
+
});
|
|
973
|
+
const closingState = this._clientClosedTerminalState();
|
|
974
|
+
this._setTerminalState({ state: closingState });
|
|
975
|
+
this._failPendingRequests(closingState.requestError());
|
|
976
|
+
void this._failToolCallStreams({ error: closingState.toolCallError() });
|
|
977
|
+
this.sync.dispose();
|
|
978
|
+
void this.messaging.stop();
|
|
979
|
+
this._protocolInstance.dispose();
|
|
980
|
+
this._entered = false;
|
|
981
|
+
this._closeKind = protocol_1.ProtocolCloseKind.CLIENT;
|
|
982
|
+
this._completeRoomClosed();
|
|
983
|
+
this._invokeTerminalCallbacks({ useErrorCallback: false });
|
|
69
984
|
this._localParticipant = null;
|
|
70
985
|
}
|
|
986
|
+
_sendProtocolNowait({ type, data, label, messageId, expectResponse = false, }) {
|
|
987
|
+
try {
|
|
988
|
+
this._raiseIfTerminal();
|
|
989
|
+
}
|
|
990
|
+
catch (error) {
|
|
991
|
+
console.debug(`skipping ${label} because the room is closed`, error);
|
|
992
|
+
return null;
|
|
993
|
+
}
|
|
994
|
+
if (this._entered && !this._connected && !this._allowDisconnectedRequests) {
|
|
995
|
+
console.debug(`skipping ${label} while room is disconnected`);
|
|
996
|
+
return null;
|
|
997
|
+
}
|
|
998
|
+
const protocol = this._protocolInstance;
|
|
999
|
+
const resolvedMessageId = messageId ?? protocol.getNextMessageId();
|
|
1000
|
+
if (expectResponse) {
|
|
1001
|
+
this._ignoredResponseLabels.set(resolvedMessageId, label);
|
|
1002
|
+
}
|
|
1003
|
+
try {
|
|
1004
|
+
protocol.sendNowait(type, data, { id: resolvedMessageId });
|
|
1005
|
+
}
|
|
1006
|
+
catch (error) {
|
|
1007
|
+
this._ignoredResponseLabels.delete(resolvedMessageId);
|
|
1008
|
+
if (this.isClosed) {
|
|
1009
|
+
console.debug(`skipping ${label} because the room is closed`, error);
|
|
1010
|
+
}
|
|
1011
|
+
else {
|
|
1012
|
+
console.warn(`unable to queue ${label}`, error);
|
|
1013
|
+
}
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
return resolvedMessageId;
|
|
1017
|
+
}
|
|
1018
|
+
_sendRoomRequestNowait(type, request, { data, label, expectResponse = false, }) {
|
|
1019
|
+
return this._sendProtocolNowait({
|
|
1020
|
+
type,
|
|
1021
|
+
data: (0, utils_1.packMessage)(request, data),
|
|
1022
|
+
label,
|
|
1023
|
+
expectResponse,
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
invokeNowait({ toolkit, tool, input, participantId, onBehalfOfId, callerContext, }) {
|
|
1027
|
+
const resolvedInput = input ?? new response_1.EmptyContent();
|
|
1028
|
+
const packedInput = (0, utils_1.unpackMessage)(resolvedInput.pack());
|
|
1029
|
+
const request = {
|
|
1030
|
+
toolkit,
|
|
1031
|
+
tool,
|
|
1032
|
+
participant_id: participantId,
|
|
1033
|
+
on_behalf_of_id: onBehalfOfId,
|
|
1034
|
+
caller_context: callerContext,
|
|
1035
|
+
tool_call_id: `${Date.now()}-${Math.random().toString(16).slice(2)}`,
|
|
1036
|
+
arguments: packedInput[0],
|
|
1037
|
+
};
|
|
1038
|
+
this._sendRoomRequestNowait("room.invoke_tool", request, {
|
|
1039
|
+
data: packedInput[1].length > 0 ? packedInput[1] : undefined,
|
|
1040
|
+
label: `${toolkit}.${tool}`,
|
|
1041
|
+
expectResponse: true,
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
_sendLocalAttributesNowait(attributes) {
|
|
1045
|
+
this._sendProtocolNowait({
|
|
1046
|
+
type: "set_attributes",
|
|
1047
|
+
data: (0, utils_1.packMessage)(attributes),
|
|
1048
|
+
label: "local participant attribute update",
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
_resendLocalAttributesNowait() {
|
|
1052
|
+
const localParticipant = this._localParticipant;
|
|
1053
|
+
if (localParticipant == null) {
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
const attributes = localParticipant._attributesSnapshot();
|
|
1057
|
+
if (Object.keys(attributes).length === 0) {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
this._sendLocalAttributesNowait(attributes);
|
|
1061
|
+
}
|
|
71
1062
|
async sendRequest(type, request, data) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
1063
|
+
this._raiseIfTerminal();
|
|
1064
|
+
if (this._entered && !this._connected && !this._allowDisconnectedRequests) {
|
|
1065
|
+
throw this._disconnectedError({ baseMessage: "room connection is disconnected" });
|
|
1066
|
+
}
|
|
1067
|
+
const requestId = this._protocolInstance.getNextMessageId();
|
|
1068
|
+
const completer = new completer_1.Completer();
|
|
1069
|
+
this._pendingRequests.set(requestId, completer);
|
|
1070
|
+
try {
|
|
1071
|
+
await this._protocolInstance.send(type, (0, utils_1.packMessage)(request, data), requestId);
|
|
1072
|
+
return await completer.fut;
|
|
1073
|
+
}
|
|
1074
|
+
catch (error) {
|
|
1075
|
+
this._pendingRequests.delete(requestId);
|
|
1076
|
+
throw error;
|
|
1077
|
+
}
|
|
78
1078
|
}
|
|
79
1079
|
async call(params) {
|
|
80
1080
|
await this.sendRequest("room.call", params);
|
|
@@ -149,7 +1149,7 @@ class RoomClient {
|
|
|
149
1149
|
return await this.sendRequest("room.invoke_tool", request, requestData);
|
|
150
1150
|
}
|
|
151
1151
|
async invokeWithStreamInput(params) {
|
|
152
|
-
const toolCallId = `${Date.now()}-${
|
|
1152
|
+
const toolCallId = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
153
1153
|
const request = {
|
|
154
1154
|
toolkit: params.toolkit,
|
|
155
1155
|
tool: params.tool,
|
|
@@ -180,7 +1180,7 @@ class RoomClient {
|
|
|
180
1180
|
}
|
|
181
1181
|
}
|
|
182
1182
|
async invokeStream(params) {
|
|
183
|
-
const toolCallId = `${Date.now()}-${
|
|
1183
|
+
const toolCallId = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
184
1184
|
const controller = new stream_controller_1.StreamController();
|
|
185
1185
|
const responseIterator = controller.stream[Symbol.asyncIterator]();
|
|
186
1186
|
this._toolCallStreams.set(toolCallId, controller);
|
|
@@ -202,7 +1202,7 @@ class RoomClient {
|
|
|
202
1202
|
const requestTask = this._streamInvokeToolRequestChunks(toolCallId, params.input);
|
|
203
1203
|
void requestTask.catch((error) => {
|
|
204
1204
|
const stream = this._toolCallStreams.get(toolCallId);
|
|
205
|
-
if (
|
|
1205
|
+
if (stream == null) {
|
|
206
1206
|
return;
|
|
207
1207
|
}
|
|
208
1208
|
stream.add(new response_1.ErrorContent({ text: `request stream failed: ${String(error)}` }));
|
|
@@ -252,8 +1252,8 @@ class RoomClient {
|
|
|
252
1252
|
}
|
|
253
1253
|
return new response_1.JsonContent({ json: { chunk } });
|
|
254
1254
|
}
|
|
255
|
-
async _handleToolCallResponseChunk(protocol,
|
|
256
|
-
if (!
|
|
1255
|
+
async _handleToolCallResponseChunk(protocol, _messageId, _type, data) {
|
|
1256
|
+
if (!this.isActiveProtocol(protocol)) {
|
|
257
1257
|
return;
|
|
258
1258
|
}
|
|
259
1259
|
const [header, payload] = (0, utils_1.unpackMessage)(data);
|
|
@@ -262,7 +1262,7 @@ class RoomClient {
|
|
|
262
1262
|
return;
|
|
263
1263
|
}
|
|
264
1264
|
const stream = this._toolCallStreams.get(toolCallId);
|
|
265
|
-
if (
|
|
1265
|
+
if (stream == null) {
|
|
266
1266
|
return;
|
|
267
1267
|
}
|
|
268
1268
|
const content = this._decodeToolCallContent({ header, payload });
|
|
@@ -272,52 +1272,92 @@ class RoomClient {
|
|
|
272
1272
|
this._toolCallStreams.delete(toolCallId);
|
|
273
1273
|
}
|
|
274
1274
|
}
|
|
275
|
-
async _handleResponse(protocol, messageId,
|
|
276
|
-
if (!
|
|
277
|
-
console.error("No data in response");
|
|
1275
|
+
async _handleResponse(protocol, messageId, _type, data) {
|
|
1276
|
+
if (!this.isActiveProtocol(protocol)) {
|
|
278
1277
|
return;
|
|
279
1278
|
}
|
|
280
1279
|
const response = (0, response_1.unpackContent)(data);
|
|
281
|
-
|
|
282
|
-
if (
|
|
283
|
-
console.error("No response");
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
if (this._pendingRequests.has(messageId)) {
|
|
287
|
-
const pr = this._pendingRequests.get(messageId);
|
|
1280
|
+
const pending = this._pendingRequests.get(messageId);
|
|
1281
|
+
if (pending != null) {
|
|
288
1282
|
this._pendingRequests.delete(messageId);
|
|
289
1283
|
if (response instanceof response_1.ErrorContent) {
|
|
290
|
-
|
|
1284
|
+
pending.completeError(new room_server_client_1.RoomServerException(response.text, response.code));
|
|
291
1285
|
}
|
|
292
1286
|
else {
|
|
293
|
-
|
|
1287
|
+
pending.complete(response);
|
|
294
1288
|
}
|
|
1289
|
+
return;
|
|
295
1290
|
}
|
|
296
|
-
|
|
297
|
-
|
|
1291
|
+
const ignoredLabel = this._ignoredResponseLabels.get(messageId);
|
|
1292
|
+
if (ignoredLabel != null) {
|
|
1293
|
+
this._ignoredResponseLabels.delete(messageId);
|
|
1294
|
+
if (response instanceof response_1.ErrorContent) {
|
|
1295
|
+
console.warn(`one-way room request failed for ${ignoredLabel}: ${response.text}`);
|
|
1296
|
+
}
|
|
298
1297
|
}
|
|
299
1298
|
}
|
|
300
|
-
async
|
|
301
|
-
|
|
302
|
-
|
|
1299
|
+
async _handleRoomStatus(protocol, _messageId, _type, data) {
|
|
1300
|
+
if (!this.isActiveProtocol(protocol)) {
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
const [payload] = (0, utils_1.unpackMessage)(data);
|
|
1304
|
+
this.emit(room_event_1.RoomStatusEvent.fromJson(payload));
|
|
1305
|
+
}
|
|
1306
|
+
async _handleRoomReady(protocol, _messageId, _type, data) {
|
|
1307
|
+
if (!this.isActiveProtocol(protocol)) {
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
const [message] = (0, utils_1.unpackMessage)(data);
|
|
1311
|
+
this._roomName = typeof message["room_name"] === "string" ? message["room_name"] : null;
|
|
1312
|
+
this._roomUrl = typeof message["room_url"] === "string" ? message["room_url"] : null;
|
|
1313
|
+
this._sessionId = typeof message["session_id"] === "string" ? message["session_id"] : null;
|
|
1314
|
+
if (!this._ready.completed) {
|
|
1315
|
+
this._ready.complete();
|
|
1316
|
+
}
|
|
1317
|
+
if (!this._connectionReady.completed) {
|
|
1318
|
+
this._connectionReady.complete();
|
|
1319
|
+
}
|
|
303
1320
|
}
|
|
304
1321
|
_onParticipantInit(participantId, attributes) {
|
|
305
|
-
this._localParticipant
|
|
306
|
-
|
|
307
|
-
this._localParticipant.
|
|
1322
|
+
if (this._localParticipant == null) {
|
|
1323
|
+
this._localParticipant = new participant_1.LocalParticipant(this, participantId);
|
|
1324
|
+
this._localParticipant._setAttributes(attributes);
|
|
1325
|
+
}
|
|
1326
|
+
else {
|
|
1327
|
+
const merged = { ...attributes, ...this._localParticipant._attributesSnapshot() };
|
|
1328
|
+
this._localParticipant._replaceIdentity({
|
|
1329
|
+
participantId,
|
|
1330
|
+
attributes: merged,
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
if (!this._localParticipantReady.completed) {
|
|
1334
|
+
this._localParticipantReady.complete();
|
|
308
1335
|
}
|
|
309
1336
|
}
|
|
310
|
-
async _handleParticipant(protocol,
|
|
311
|
-
|
|
1337
|
+
async _handleParticipant(protocol, _messageId, _type, data) {
|
|
1338
|
+
if (!this.isActiveProtocol(protocol)) {
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
const [message] = (0, utils_1.unpackMessage)(data);
|
|
312
1342
|
switch (message["type"]) {
|
|
313
|
-
case "init":
|
|
1343
|
+
case "init": {
|
|
1344
|
+
const participantId = message["participantId"];
|
|
1345
|
+
const attributes = message["attributes"];
|
|
1346
|
+
if (typeof participantId === "string" &&
|
|
1347
|
+
typeof attributes === "object" &&
|
|
1348
|
+
attributes !== null &&
|
|
1349
|
+
!Array.isArray(attributes)) {
|
|
1350
|
+
this._onParticipantInit(participantId, attributes);
|
|
1351
|
+
}
|
|
1352
|
+
break;
|
|
1353
|
+
}
|
|
1354
|
+
default:
|
|
1355
|
+
break;
|
|
314
1356
|
}
|
|
315
1357
|
}
|
|
316
|
-
|
|
317
|
-
this.
|
|
318
|
-
}
|
|
319
|
-
listen() {
|
|
320
|
-
return this._eventsController.stream;
|
|
1358
|
+
_emitStatus({ status, message, }) {
|
|
1359
|
+
this.emit(new room_event_1.RoomStatusEvent({ status, message }));
|
|
321
1360
|
}
|
|
322
1361
|
}
|
|
323
1362
|
exports.RoomClient = RoomClient;
|
|
1363
|
+
RoomClient.RECONNECT_RETRY_INTERVAL_MS = 1000;
|