@meshagent/meshagent 0.35.6 → 0.35.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/browser/containers-client.d.ts +79 -2
  3. package/dist/browser/containers-client.js +341 -19
  4. package/dist/browser/database-client.d.ts +95 -24
  5. package/dist/browser/database-client.js +150 -49
  6. package/dist/browser/messaging-client.d.ts +33 -52
  7. package/dist/browser/messaging-client.js +180 -184
  8. package/dist/browser/participant.d.ts +5 -3
  9. package/dist/browser/participant.js +9 -1
  10. package/dist/browser/room-client.js +2 -0
  11. package/dist/browser/room-event.d.ts +6 -2
  12. package/dist/browser/room-event.js +4 -2
  13. package/dist/browser/secrets-client.d.ts +86 -16
  14. package/dist/browser/secrets-client.js +243 -44
  15. package/dist/browser/storage-client.d.ts +17 -4
  16. package/dist/browser/storage-client.js +104 -16
  17. package/dist/esm/containers-client.d.ts +79 -2
  18. package/dist/esm/containers-client.js +341 -19
  19. package/dist/esm/database-client.d.ts +95 -24
  20. package/dist/esm/database-client.js +150 -49
  21. package/dist/esm/messaging-client.d.ts +33 -52
  22. package/dist/esm/messaging-client.js +179 -180
  23. package/dist/esm/participant.d.ts +5 -3
  24. package/dist/esm/participant.js +9 -1
  25. package/dist/esm/room-client.js +2 -0
  26. package/dist/esm/room-event.d.ts +6 -2
  27. package/dist/esm/room-event.js +4 -2
  28. package/dist/esm/secrets-client.d.ts +86 -16
  29. package/dist/esm/secrets-client.js +243 -44
  30. package/dist/esm/storage-client.d.ts +17 -4
  31. package/dist/esm/storage-client.js +103 -16
  32. package/dist/node/containers-client.d.ts +79 -2
  33. package/dist/node/containers-client.js +341 -19
  34. package/dist/node/database-client.d.ts +95 -24
  35. package/dist/node/database-client.js +150 -49
  36. package/dist/node/messaging-client.d.ts +33 -52
  37. package/dist/node/messaging-client.js +180 -184
  38. package/dist/node/participant.d.ts +5 -3
  39. package/dist/node/participant.js +9 -1
  40. package/dist/node/room-client.js +2 -0
  41. package/dist/node/room-event.d.ts +6 -2
  42. package/dist/node/room-event.js +4 -2
  43. package/dist/node/secrets-client.d.ts +86 -16
  44. package/dist/node/secrets-client.js +243 -44
  45. package/dist/node/storage-client.d.ts +17 -4
  46. package/dist/node/storage-client.js +104 -16
  47. package/package.json +1 -1
@@ -1,14 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MessageStreamReader = exports.MessageStreamWriter = exports.MessagingClient = exports.MessageStreamChunk = void 0;
4
- const uuid_1 = require("uuid");
3
+ exports.MessagingClient = void 0;
5
4
  const event_emitter_1 = require("./event-emitter");
5
+ const completer_1 = require("./completer");
6
6
  const participant_1 = require("./participant");
7
7
  const room_event_1 = require("./room-event");
8
8
  const room_server_client_1 = require("./room-server-client");
9
9
  const utils_1 = require("./utils");
10
- const stream_controller_1 = require("./stream-controller");
11
- const completer_1 = require("./completer");
12
10
  const globalScope = globalThis;
13
11
  function bytesToBase64(bytes) {
14
12
  if (globalScope.Buffer) {
@@ -23,21 +21,18 @@ function bytesToBase64(bytes) {
23
21
  }
24
22
  return globalScope.btoa(binary);
25
23
  }
26
- class MessageStreamChunk {
27
- constructor({ header, data }) {
28
- this.header = header;
29
- this.data = data;
30
- }
31
- }
32
- exports.MessageStreamChunk = MessageStreamChunk;
33
24
  class MessagingClient extends event_emitter_1.EventEmitter {
34
25
  constructor({ room }) {
35
26
  super();
36
- this._streamWriters = {};
37
- this._streamReaders = {};
27
+ this._messageHandler = this._handleMessageSend.bind(this);
38
28
  this._participants = {};
29
+ this._messageQueue = [];
30
+ this._messageQueued = null;
31
+ this._sendTask = null;
32
+ this._messageQueueClosed = false;
33
+ this._enabled = false;
39
34
  this.client = room;
40
- this.client.protocol.addHandler("messaging.send", this._handleMessageSend.bind(this));
35
+ this.client.protocol.addHandler("messaging.send", this._messageHandler);
41
36
  }
42
37
  _messageInput(params) {
43
38
  const input = {
@@ -52,6 +47,16 @@ class MessagingClient extends event_emitter_1.EventEmitter {
52
47
  }
53
48
  return input;
54
49
  }
50
+ _syntheticMessageEvent(params) {
51
+ return new room_event_1.RoomMessageEvent({
52
+ message: new room_event_1.RoomMessage({
53
+ fromParticipantId: params.fromParticipantId,
54
+ type: params.type,
55
+ message: params.message,
56
+ local: true,
57
+ }),
58
+ });
59
+ }
55
60
  _removeParticipant(participantId) {
56
61
  const participant = this._participants[participantId];
57
62
  if (participant === undefined) {
@@ -59,15 +64,24 @@ class MessagingClient extends event_emitter_1.EventEmitter {
59
64
  }
60
65
  participant._setOnline(false);
61
66
  delete this._participants[participantId];
62
- for (const [streamId, reader] of Object.entries(this._streamReaders)) {
63
- if (reader._to.id !== participant.id) {
64
- continue;
65
- }
66
- reader._controller.close();
67
- delete this._streamReaders[streamId];
68
- }
69
67
  return participant;
70
68
  }
69
+ _markParticipantOffline(participant) {
70
+ if (!(participant instanceof participant_1.RemoteParticipant)) {
71
+ return;
72
+ }
73
+ participant._setOnline(false);
74
+ const current = this._participants[participant.id];
75
+ if (current === undefined) {
76
+ return;
77
+ }
78
+ this._removeParticipant(participant.id);
79
+ this.emit("participant_removed", this._syntheticMessageEvent({
80
+ fromParticipantId: participant.id,
81
+ type: "participant.disabled",
82
+ message: { id: participant.id },
83
+ }));
84
+ }
71
85
  _resolveMessageRecipient(to) {
72
86
  if (!(to instanceof participant_1.RemoteParticipant)) {
73
87
  return to;
@@ -77,46 +91,131 @@ class MessagingClient extends event_emitter_1.EventEmitter {
77
91
  }
78
92
  return this._participants[to.id] ?? null;
79
93
  }
80
- _participantNotFound(ignoreOffline) {
81
- if (ignoreOffline) {
82
- return null;
94
+ _queueMessage(message) {
95
+ if (this._sendTask === null) {
96
+ throw new room_server_client_1.RoomServerException("Cannot send messages because messaging has not been started");
97
+ }
98
+ this._messageQueue.push(message);
99
+ const waiter = this._messageQueued;
100
+ if (waiter !== null) {
101
+ this._messageQueued = null;
102
+ waiter.complete();
103
+ }
104
+ }
105
+ _rejectQueuedMessages(error) {
106
+ while (this._messageQueue.length > 0) {
107
+ const message = this._messageQueue.shift();
108
+ message?.completer?.completeError(error);
109
+ }
110
+ }
111
+ _isParticipantNotFound(error) {
112
+ return error instanceof room_server_client_1.RoomServerException && error.message === "the participant was not found";
113
+ }
114
+ async _nextQueuedMessage() {
115
+ while (this._messageQueue.length === 0) {
116
+ if (this._messageQueueClosed) {
117
+ return null;
118
+ }
119
+ if (this._messageQueued === null) {
120
+ this._messageQueued = new completer_1.Completer();
121
+ }
122
+ await this._messageQueued.fut;
123
+ }
124
+ return this._messageQueue.shift() ?? null;
125
+ }
126
+ async _sendMessages() {
127
+ while (true) {
128
+ const queued = await this._nextQueuedMessage();
129
+ if (queued === null) {
130
+ return;
131
+ }
132
+ const resolvedTo = this._resolveMessageRecipient(queued.to);
133
+ if (resolvedTo === null) {
134
+ const error = new room_server_client_1.RoomServerException("the participant was not found");
135
+ if (queued.dropIfOffline) {
136
+ queued.completer?.complete();
137
+ }
138
+ else {
139
+ queued.completer?.completeError(error);
140
+ }
141
+ continue;
142
+ }
143
+ try {
144
+ await this.client.invoke({
145
+ toolkit: "messaging",
146
+ tool: "send",
147
+ input: this._messageInput({
148
+ toParticipantId: resolvedTo.id,
149
+ type: queued.type,
150
+ message: queued.message,
151
+ attachment: queued.attachment,
152
+ }),
153
+ });
154
+ queued.completer?.complete();
155
+ }
156
+ catch (error) {
157
+ if (this._isParticipantNotFound(error)) {
158
+ this._markParticipantOffline(queued.to);
159
+ if (queued.dropIfOffline) {
160
+ queued.completer?.complete();
161
+ continue;
162
+ }
163
+ }
164
+ queued.completer?.completeError(error);
165
+ }
83
166
  }
84
- throw new room_server_client_1.RoomServerException("the participant was not found");
85
167
  }
86
- async createStream({ to, header }) {
87
- const streamId = (0, uuid_1.v4)();
168
+ async start() {
169
+ if (this._sendTask !== null) {
170
+ return;
171
+ }
172
+ this._messageQueueClosed = false;
173
+ this._sendTask = this._sendMessages();
174
+ }
175
+ async stop() {
176
+ if (this._sendTask === null) {
177
+ this._enabled = false;
178
+ return;
179
+ }
180
+ this._messageQueueClosed = true;
181
+ const waiter = this._messageQueued;
182
+ if (waiter !== null) {
183
+ this._messageQueued = null;
184
+ waiter.complete();
185
+ }
186
+ const sendTask = this._sendTask;
187
+ this._sendTask = null;
188
+ await sendTask;
189
+ this._enabled = false;
190
+ }
191
+ async sendMessage({ to, type, message, attachment, ignoreOffline = false }) {
88
192
  const completer = new completer_1.Completer();
89
- this._streamWriters[streamId] = completer;
90
- await this.sendMessage({
193
+ this._queueMessage({
91
194
  to,
92
- type: "stream.open",
93
- message: { stream_id: streamId, header },
195
+ type,
196
+ message,
197
+ attachment,
198
+ dropIfOffline: ignoreOffline,
199
+ completer,
94
200
  });
95
- return completer.fut;
201
+ await completer.fut;
96
202
  }
97
- async sendMessage({ to, type, message, attachment, ignoreOffline = false }) {
98
- const resolvedTo = this._resolveMessageRecipient(to) ?? this._participantNotFound(ignoreOffline);
99
- if (resolvedTo === null) {
100
- return;
101
- }
102
- await this.client.invoke({
103
- toolkit: "messaging",
104
- tool: "send",
105
- input: this._messageInput({
106
- toParticipantId: resolvedTo.id,
107
- type,
108
- message,
109
- attachment,
110
- }),
203
+ sendMessageNowait({ to, type, message, attachment }) {
204
+ this._queueMessage({
205
+ to,
206
+ type,
207
+ message,
208
+ attachment,
209
+ dropIfOffline: true,
111
210
  });
112
211
  }
113
- async enable(onStreamAccept) {
212
+ async enable() {
114
213
  await this.client.invoke({
115
214
  toolkit: "messaging",
116
215
  tool: "enable",
117
216
  input: {},
118
217
  });
119
- this._onStreamAcceptCallback = onStreamAccept;
218
+ this._enabled = true;
120
219
  }
121
220
  async disable() {
122
221
  await this.client.invoke({
@@ -124,6 +223,7 @@ class MessagingClient extends event_emitter_1.EventEmitter {
124
223
  tool: "disable",
125
224
  input: {},
126
225
  });
226
+ this._enabled = false;
127
227
  }
128
228
  async broadcastMessage({ type, message, attachment }) {
129
229
  await this.client.invoke({
@@ -135,6 +235,23 @@ class MessagingClient extends event_emitter_1.EventEmitter {
135
235
  get remoteParticipants() {
136
236
  return Object.values(this._participants);
137
237
  }
238
+ get isEnabled() {
239
+ return this._enabled;
240
+ }
241
+ getParticipants() {
242
+ return this.remoteParticipants;
243
+ }
244
+ getParticipant(id) {
245
+ return this._participants[id] ?? null;
246
+ }
247
+ getParticipantByName(name) {
248
+ for (const participant of this.remoteParticipants) {
249
+ if (participant.getAttribute("name") === name) {
250
+ return participant;
251
+ }
252
+ }
253
+ return null;
254
+ }
138
255
  async _handleMessageSend(protocol, messageId, type, bytes) {
139
256
  const headerStr = (0, utils_1.splitMessageHeader)(bytes || new Uint8Array());
140
257
  const payload = (0, utils_1.splitMessagePayload)(bytes || new Uint8Array());
@@ -158,21 +275,6 @@ class MessagingClient extends event_emitter_1.EventEmitter {
158
275
  case "participant.disabled":
159
276
  this._onParticipantDisabled(message);
160
277
  break;
161
- case "stream.open":
162
- this._onStreamOpen(message);
163
- break;
164
- case "stream.accept":
165
- this._onStreamAccept(message);
166
- break;
167
- case "stream.reject":
168
- this._onStreamReject(message);
169
- break;
170
- case "stream.chunk":
171
- this._onStreamChunk(message);
172
- break;
173
- case "stream.close":
174
- this._onStreamClose(message);
175
- break;
176
278
  }
177
279
  const messageEvent = new room_event_1.RoomMessageEvent({ message });
178
280
  this.client.emit(messageEvent);
@@ -181,20 +283,17 @@ class MessagingClient extends event_emitter_1.EventEmitter {
181
283
  _onParticipantEnabled(message) {
182
284
  const data = message.message;
183
285
  const p = new participant_1.RemoteParticipant(this.client, data["id"], data["role"], true);
184
- for (const [k, v] of Object.entries(data["attributes"] || {})) {
185
- p._attributes[k] = v;
186
- }
286
+ p._setAttributes(data["attributes"] ?? {});
187
287
  this._participants[data["id"]] = p;
188
288
  this.emit("participant_added", { message });
189
289
  }
190
290
  _onParticipantAttributes(message) {
191
291
  const part = this._participants[message.fromParticipantId];
192
- if (!part)
292
+ if (!part) {
193
293
  return;
194
- const attrObj = message.message["attributes"];
195
- for (const [k, v] of Object.entries(attrObj)) {
196
- part._attributes[k] = v;
197
294
  }
295
+ const attrObj = message.message["attributes"];
296
+ part._setAttributes(attrObj);
198
297
  this.emit("participant_attributes_updated", { message });
199
298
  }
200
299
  _onParticipantDisabled(message) {
@@ -207,127 +306,24 @@ class MessagingClient extends event_emitter_1.EventEmitter {
207
306
  const participants = message.message["participants"];
208
307
  for (const data of participants) {
209
308
  const rp = new participant_1.RemoteParticipant(this.client, data["id"], data["role"], true);
210
- for (const [k, v] of Object.entries(data["attributes"] || {})) {
211
- rp._attributes[k] = v;
212
- }
309
+ rp._setAttributes(data["attributes"] ?? {});
213
310
  this._participants[data["id"]] = rp;
214
311
  }
312
+ this._enabled = true;
215
313
  this.emit("messaging_enabled", { message });
216
314
  }
217
- _onStreamOpen(message) {
218
- const from = [...this.remoteParticipants]
219
- .find((x) => x.id === message.fromParticipantId);
220
- if (!from)
221
- return;
222
- const streamId = message.message["stream_id"];
223
- const controller = new stream_controller_1.StreamController();
224
- const reader = new MessageStreamReader({
225
- streamId,
226
- to: from,
227
- client: this,
228
- controller,
229
- });
230
- try {
231
- if (!this._onStreamAcceptCallback) {
232
- throw new Error("streams are not allowed by this client");
233
- }
234
- this._onStreamAcceptCallback(reader);
235
- void this.sendMessage({
236
- to: from,
237
- type: "stream.accept",
238
- message: { stream_id: streamId },
239
- ignoreOffline: true,
240
- }).catch((error) => {
241
- console.warn("unable to send stream response", error);
242
- });
243
- }
244
- catch (e) {
245
- void this.sendMessage({
246
- to: from,
247
- type: "stream.reject",
248
- message: { stream_id: streamId, error: String(e) },
249
- ignoreOffline: true,
250
- }).catch((error) => {
251
- console.warn("unable to send stream response", error);
252
- });
253
- }
254
- this._streamReaders[streamId] = reader;
255
- this.emit("stream_opened", { message });
256
- }
257
- _onStreamAccept(message) {
258
- const streamId = message.message["stream_id"];
259
- const writerCompleter = this._streamWriters[streamId];
260
- if (!writerCompleter)
261
- return;
262
- const from = [...this.remoteParticipants].find((x) => x.id === message.fromParticipantId);
263
- if (!from)
264
- return;
265
- writerCompleter.complete(new MessageStreamWriter({
266
- streamId,
267
- to: from,
268
- client: this,
269
- }));
270
- }
271
- _onStreamReject(message) {
272
- const streamId = message.message["stream_id"];
273
- const writerCompleter = this._streamWriters[streamId];
274
- if (!writerCompleter)
275
- return;
276
- writerCompleter.completeError(new Error("The stream was rejected by the remote client"));
277
- }
278
- _onStreamChunk(message) {
279
- const streamId = message.message["stream_id"];
280
- const reader = this._streamReaders[streamId];
281
- if (!reader)
282
- return;
283
- reader._controller.add(new MessageStreamChunk({
284
- header: message.message,
285
- data: message.attachment,
286
- }));
287
- }
288
- _onStreamClose(message) {
289
- const streamId = message.message["stream_id"];
290
- const reader = this._streamReaders[streamId];
291
- if (!reader)
292
- return;
293
- reader._controller.close();
294
- delete this._streamReaders[streamId];
295
- }
296
315
  dispose() {
316
+ const error = new room_server_client_1.RoomServerException("messaging client disposed");
317
+ this._messageQueueClosed = true;
318
+ this._enabled = false;
319
+ this._rejectQueuedMessages(error);
320
+ const waiter = this._messageQueued;
321
+ if (waiter !== null) {
322
+ this._messageQueued = null;
323
+ waiter.complete();
324
+ }
297
325
  super.dispose();
298
326
  this.client.protocol.removeHandler("messaging.send");
299
327
  }
300
328
  }
301
329
  exports.MessagingClient = MessagingClient;
302
- class MessageStreamWriter {
303
- constructor({ streamId, to, client }) {
304
- this._streamId = streamId;
305
- this._to = to;
306
- this._client = client;
307
- }
308
- async write(chunk) {
309
- await this._client.sendMessage({
310
- to: this._to,
311
- type: "stream.chunk",
312
- message: { stream_id: this._streamId, header: chunk.header },
313
- attachment: chunk.data,
314
- });
315
- }
316
- async close() {
317
- await this._client.sendMessage({
318
- to: this._to,
319
- type: "stream.close",
320
- message: { stream_id: this._streamId },
321
- });
322
- }
323
- }
324
- exports.MessageStreamWriter = MessageStreamWriter;
325
- class MessageStreamReader {
326
- constructor({ streamId, to, client, controller }) {
327
- this._streamId = streamId;
328
- this._to = to;
329
- this._client = client;
330
- this._controller = controller;
331
- }
332
- }
333
- exports.MessageStreamReader = MessageStreamReader;
@@ -2,11 +2,13 @@ import { RoomClient } from "./room-client";
2
2
  export declare abstract class Participant {
3
3
  readonly id: string;
4
4
  protected readonly client: RoomClient;
5
- protected _attributes: Record<string, any>;
5
+ protected _attributes: Record<string, unknown>;
6
6
  protected _connections: string[];
7
7
  constructor(client: RoomClient, id: string);
8
8
  get connections(): ReadonlyArray<string>;
9
- getAttribute(name: string): any;
9
+ getAttribute(name: string): unknown;
10
+ _setAttribute(name: string, value: unknown): void;
11
+ _setAttributes(attributes: Record<string, unknown>): void;
10
12
  }
11
13
  export declare class RemoteParticipant extends Participant {
12
14
  readonly role: string;
@@ -16,5 +18,5 @@ export declare class RemoteParticipant extends Participant {
16
18
  }
17
19
  export declare class LocalParticipant extends Participant {
18
20
  constructor(client: RoomClient, id: string);
19
- setAttribute(name: string, value: any): Promise<void>;
21
+ setAttribute(name: string, value: unknown): Promise<void>;
20
22
  }
@@ -15,6 +15,14 @@ class Participant {
15
15
  getAttribute(name) {
16
16
  return this._attributes[name];
17
17
  }
18
+ _setAttribute(name, value) {
19
+ this._attributes[name] = value;
20
+ }
21
+ _setAttributes(attributes) {
22
+ for (const [name, value] of Object.entries(attributes)) {
23
+ this._setAttribute(name, value);
24
+ }
25
+ }
18
26
  }
19
27
  exports.Participant = Participant;
20
28
  class RemoteParticipant extends Participant {
@@ -33,7 +41,7 @@ class LocalParticipant extends Participant {
33
41
  super(client, id);
34
42
  }
35
43
  async setAttribute(name, value) {
36
- this._attributes[name] = value;
44
+ this._setAttribute(name, value);
37
45
  try {
38
46
  const payload = (0, utils_1.packMessage)({ [name]: value });
39
47
  await this.client.protocol.send("set_attributes", payload);
@@ -49,6 +49,7 @@ class RoomClient {
49
49
  return this._ready.fut;
50
50
  }
51
51
  async start({ onDone, onError } = {}) {
52
+ await this.messaging.start();
52
53
  this.sync.start({ onDone, onError });
53
54
  await this.ready;
54
55
  }
@@ -58,6 +59,7 @@ class RoomClient {
58
59
  pr?.reject(new Error("Disposed"));
59
60
  this._pendingRequests.delete(prKey);
60
61
  }
62
+ this.messaging.dispose();
61
63
  this.sync.dispose();
62
64
  for (const stream of this._toolCallStreams.values()) {
63
65
  stream.close();
@@ -34,16 +34,20 @@ export declare class FileCreatedEvent extends RoomEvent {
34
34
  }
35
35
  export declare class FileDeletedEvent extends RoomEvent {
36
36
  path: string;
37
- constructor({ path }: {
37
+ participantId: string;
38
+ constructor({ path, participantId }: {
38
39
  path: string;
40
+ participantId: string;
39
41
  });
40
42
  get name(): string;
41
43
  get description(): string;
42
44
  }
43
45
  export declare class FileUpdatedEvent extends RoomEvent {
44
46
  path: string;
45
- constructor({ path }: {
47
+ participantId: string;
48
+ constructor({ path, participantId }: {
46
49
  path: string;
50
+ participantId: string;
47
51
  });
48
52
  get name(): string;
49
53
  get description(): string;
@@ -41,9 +41,10 @@ class FileCreatedEvent extends RoomEvent {
41
41
  }
42
42
  exports.FileCreatedEvent = FileCreatedEvent;
43
43
  class FileDeletedEvent extends RoomEvent {
44
- constructor({ path }) {
44
+ constructor({ path, participantId }) {
45
45
  super();
46
46
  this.path = path;
47
+ this.participantId = participantId;
47
48
  }
48
49
  get name() {
49
50
  return "file deleted";
@@ -54,9 +55,10 @@ class FileDeletedEvent extends RoomEvent {
54
55
  }
55
56
  exports.FileDeletedEvent = FileDeletedEvent;
56
57
  class FileUpdatedEvent extends RoomEvent {
57
- constructor({ path }) {
58
+ constructor({ path, participantId }) {
58
59
  super();
59
60
  this.path = path;
61
+ this.participantId = participantId;
60
62
  }
61
63
  get name() {
62
64
  return "file updated";