@meshagent/meshagent-agents 0.47.0 → 0.48.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.
@@ -1,19 +1,40 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ChatThreadSession = exports.MessagingChatClient = exports.BaseChatClient = exports.ChatThreadStartResult = exports.ChatThreadSessionLoadState = exports.ChatThreadSessionLoadPhase = exports.PendingAgentInput = exports.AgentMessageEvent = void 0;
6
+ exports.ChatThreadSession = exports.MessagingChatClient = exports.WebSocketChatClient = exports.BaseMessagingChatClient = exports.ThreadListSubscribe = exports.ThreadSubscribe = exports.messagingChatThreadListSubscribeType = exports.messagingChatThreadSubscribeType = exports.BaseChatClient = exports.PendingThreadStartCandidate = exports.ChatThreadStartResult = exports.ChatThreadSessionLoadState = exports.ChatThreadSessionLoadPhase = exports.PendingAgentInput = exports.AgentMessageEvent = void 0;
4
7
  const meshagent_1 = require("@meshagent/meshagent");
8
+ const msgpack_1 = require("@msgpack/msgpack");
9
+ const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
5
10
  const uuid_1 = require("uuid");
6
11
  const agent_messages_js_1 = require("./agent-messages.js");
7
12
  const change_emitter_js_1 = require("./change-emitter.js");
8
13
  class AgentMessageEvent {
9
14
  constructor({ message, createdAt, attachment }) {
10
- this.message = message;
11
- this.createdAt = createdAt ?? dateOrNull(message.createdAt) ?? new Date();
15
+ this.listeners = new Set();
16
+ this.messageValue = message;
17
+ this.createdAt = createdAt ?? message.createdAtUtc ?? new Date();
12
18
  this.attachment = attachment;
13
19
  }
20
+ get message() {
21
+ return this.messageValue;
22
+ }
14
23
  get payload() {
15
24
  return { ...this.message.toJson(), created_at: this.createdAt.toISOString() };
16
25
  }
26
+ addEventListener(listener) {
27
+ this.listeners.add(listener);
28
+ }
29
+ removeEventListener(listener) {
30
+ this.listeners.delete(listener);
31
+ }
32
+ replaceMessage(message) {
33
+ this.messageValue = message;
34
+ for (const listener of [...this.listeners]) {
35
+ listener();
36
+ }
37
+ }
17
38
  }
18
39
  exports.AgentMessageEvent = AgentMessageEvent;
19
40
  function agentRoomMessageFromEvent(event) {
@@ -99,6 +120,13 @@ class ChatThreadStartResult {
99
120
  }
100
121
  }
101
122
  exports.ChatThreadStartResult = ChatThreadStartResult;
123
+ class PendingThreadStartCandidate {
124
+ constructor({ messageId, senderName }) {
125
+ this.messageId = messageId;
126
+ this.senderName = senderName;
127
+ }
128
+ }
129
+ exports.PendingThreadStartCandidate = PendingThreadStartCandidate;
102
130
  class EventQueue {
103
131
  constructor() {
104
132
  this.subscribers = new Set();
@@ -151,12 +179,15 @@ class EventQueue {
151
179
  }
152
180
  }
153
181
  class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
154
- constructor() {
155
- super(...arguments);
182
+ constructor({ threadCreatedPendingStartMatcher, deduplicateClientToolRequests = false, } = {}) {
183
+ super();
156
184
  this.sessionsByPath = new Map();
157
185
  this.pendingStartRequests = new Map();
158
186
  this.pendingSessionEventsByPath = new Map();
159
187
  this.eventQueue = new EventQueue();
188
+ this.claimedClientToolRequests = new Set();
189
+ this.threadCreatedPendingStartMatcher = threadCreatedPendingStartMatcher;
190
+ this.deduplicateClientToolRequests = deduplicateClientToolRequests;
160
191
  }
161
192
  get events() {
162
193
  return this.eventQueue.stream;
@@ -178,14 +209,41 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
178
209
  localParticipantId() {
179
210
  return undefined;
180
211
  }
181
- isClientToolCallForLocalParticipant(request) {
182
- const targetParticipantId = request.targetParticipantId?.trim();
183
- return targetParticipantId == null || targetParticipantId === "" || targetParticipantId === this.localParticipantId();
212
+ clientToolRequestKey(threadPath, requestId) {
213
+ const normalizedThreadPath = threadPath.trim();
214
+ const normalizedRequestId = requestId.trim();
215
+ if (normalizedThreadPath === "" || normalizedRequestId === "") {
216
+ return undefined;
217
+ }
218
+ return `${normalizedThreadPath}\n${normalizedRequestId}`;
219
+ }
220
+ claimClientToolRequest(threadPath, requestId) {
221
+ if (!this.deduplicateClientToolRequests) {
222
+ return true;
223
+ }
224
+ const key = this.clientToolRequestKey(threadPath, requestId);
225
+ if (key == null) {
226
+ return true;
227
+ }
228
+ if (this.claimedClientToolRequests.has(key)) {
229
+ return false;
230
+ }
231
+ this.claimedClientToolRequests.add(key);
232
+ return true;
233
+ }
234
+ finishClientToolRequest(threadPath, requestId, { responseSent }) {
235
+ if (!this.deduplicateClientToolRequests || responseSent) {
236
+ return;
237
+ }
238
+ const key = this.clientToolRequestKey(threadPath, requestId);
239
+ if (key != null) {
240
+ this.claimedClientToolRequests.delete(key);
241
+ }
184
242
  }
185
243
  cleanParticipantName(value) {
186
244
  return nonEmptyTrimmed(value);
187
245
  }
188
- openThread(threadPath, { load = true, sinceTurn, reloadIfOpen = false, drainPendingEvents = true, } = {}) {
246
+ openThread(threadPath, { load = true, sinceTurn, reloadIfOpen = false, } = {}) {
189
247
  const normalized = threadPath.trim();
190
248
  if (normalized === "") {
191
249
  throw new TypeError("thread path cannot be empty");
@@ -197,11 +255,8 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
197
255
  }
198
256
  return existing;
199
257
  }
200
- const created = new ChatThreadSession({ client: this, threadPath: normalized });
258
+ const created = ChatThreadSession.create({ client: this, threadPath: normalized });
201
259
  this.sessionsByPath.set(normalized, created);
202
- if (drainPendingEvents) {
203
- this.drainPendingSessionEvents(normalized, created);
204
- }
205
260
  this.openSession(created, { load, sinceTurn });
206
261
  this.notifyListeners();
207
262
  return created;
@@ -211,7 +266,7 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
211
266
  this.notifyListeners();
212
267
  });
213
268
  }
214
- async startThread({ messageId, message, attachments, name, backend, provider, model, voice, outputModalities, realtimeProtocol, senderName, clientToolkits, toolChoice, omitContent = false, }) {
269
+ async startThread({ messageId, message, attachments, name, backend, provider, model, voice, outputModalities, realtimeProtocol, senderName, clientToolkits, omitContent = false, }) {
215
270
  const resolvedMessageId = messageId == null || messageId.trim() === "" ? (0, uuid_1.v4)() : messageId.trim();
216
271
  const resolvedSenderName = this.cleanParticipantName(senderName) ?? this.localParticipantName();
217
272
  const payload = new agent_messages_js_1.StartThread({
@@ -226,10 +281,9 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
226
281
  realtimeProtocol: nonEmptyTrimmed(realtimeProtocol),
227
282
  senderName: resolvedSenderName,
228
283
  clientToolkits: clientToolkits != null && clientToolkits.length > 0 ? clientToolkits : undefined,
229
- toolChoice: toolChoice?.toJson(),
230
284
  });
231
285
  const completer = new meshagent_1.Completer();
232
- this.pendingStartRequests.set(resolvedMessageId, completer);
286
+ this.pendingStartRequests.set(resolvedMessageId, { request: payload, completer });
233
287
  try {
234
288
  await this.sendAgentMessage(payload);
235
289
  const response = await completer.fut;
@@ -239,18 +293,18 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
239
293
  if (threadPath === "") {
240
294
  throw new Error("Agent did not return a thread_id for the new thread.");
241
295
  }
242
- const session = this.openThread(threadPath, { load: false, drainPendingEvents: false });
296
+ const session = this.openThread(threadPath, { load: false });
243
297
  if (!omitContent) {
244
298
  session.addAgentMessage(new AgentMessageEvent({
245
299
  message: this.resolvedStartThreadMessage({ payload, threadPath }),
246
- createdAt: dateOrNull(payload.createdAt) ?? undefined,
300
+ createdAt: payload.createdAtUtc,
247
301
  }));
248
302
  }
249
303
  this.drainPendingSessionEvents(threadPath, session);
250
304
  return new ChatThreadStartResult({
251
305
  session,
252
306
  threadPath,
253
- realtimeConnection: response.type === agent_messages_js_1.agentThreadStartedType && response.realtimeConnection != null
307
+ realtimeConnection: response instanceof agent_messages_js_1.ThreadStarted && response.realtimeConnection != null
254
308
  ? response.realtimeConnection.toJson()
255
309
  : undefined,
256
310
  });
@@ -274,6 +328,7 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
274
328
  mcp: payload.mcp,
275
329
  clientToolkits: payload.clientToolkits,
276
330
  toolkits: payload.toolkits,
331
+ toolChoice: payload.toolChoice,
277
332
  });
278
333
  }
279
334
  drainPendingSessionEvents(threadPath, session) {
@@ -287,9 +342,13 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
287
342
  }
288
343
  }
289
344
  handleAgentMessage(message, { createdAt, attachment } = {}) {
290
- if (message instanceof agent_messages_js_1.AgentClientToolCallRequested &&
291
- !this.isClientToolCallForLocalParticipant(message)) {
292
- return;
345
+ if (message instanceof agent_messages_js_1.AgentClientToolCallRequested) {
346
+ const targetParticipantId = message.targetParticipantId?.trim();
347
+ if (targetParticipantId != null &&
348
+ targetParticipantId !== "" &&
349
+ targetParticipantId !== this.localParticipantId()) {
350
+ return;
351
+ }
293
352
  }
294
353
  if (message.type === agent_messages_js_1.agentConnectionStatusType) {
295
354
  this._connectionStatus = message;
@@ -300,10 +359,13 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
300
359
  sourceMessageId != null &&
301
360
  sourceMessageId.trim() !== "") {
302
361
  const pending = this.pendingStartRequests.get(sourceMessageId.trim());
303
- if (pending != null && !pending.completed) {
304
- pending.complete(message);
362
+ if (pending != null && !pending.completer.completed) {
363
+ pending.completer.complete(message);
305
364
  }
306
365
  }
366
+ if (message instanceof agent_messages_js_1.ThreadCreated) {
367
+ this.acknowledgePendingStartFromThreadCreated(message);
368
+ }
307
369
  const threadPath = "threadId" in message ? String(message.threadId).trim() : "";
308
370
  if (threadPath === "") {
309
371
  this.notifyListeners();
@@ -321,6 +383,40 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
321
383
  }
322
384
  this.notifyListeners();
323
385
  }
386
+ acknowledgePendingStartFromThreadCreated(message) {
387
+ const matcher = this.threadCreatedPendingStartMatcher;
388
+ const threadPath = String(message.thread?.path ?? "").trim();
389
+ if (matcher == null || threadPath === "") {
390
+ return;
391
+ }
392
+ const candidates = [...this.pendingStartRequests.entries()]
393
+ .filter(([, pending]) => !pending.completer.completed)
394
+ .map(([messageId, pending]) => new PendingThreadStartCandidate({
395
+ messageId,
396
+ senderName: pending.request.senderName,
397
+ }));
398
+ if (candidates.length === 0) {
399
+ return;
400
+ }
401
+ let matchedMessageId;
402
+ try {
403
+ matchedMessageId = matcher(message, candidates)?.trim();
404
+ }
405
+ catch {
406
+ return;
407
+ }
408
+ if (matchedMessageId == null || matchedMessageId === "") {
409
+ return;
410
+ }
411
+ const pending = this.pendingStartRequests.get(matchedMessageId);
412
+ if (pending == null || pending.completer.completed) {
413
+ return;
414
+ }
415
+ pending.completer.complete(new agent_messages_js_1.ThreadStarted({
416
+ sourceMessageId: matchedMessageId,
417
+ threadId: threadPath,
418
+ }));
419
+ }
324
420
  emitConnectionStatus({ status, message, reason, retryDelay, }) {
325
421
  const event = new agent_messages_js_1.AgentConnectionStatus({
326
422
  status,
@@ -343,9 +439,51 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
343
439
  }
344
440
  }
345
441
  exports.BaseChatClient = BaseChatClient;
346
- class MessagingChatClient extends BaseChatClient {
347
- constructor({ room, agentName }) {
348
- super();
442
+ exports.messagingChatThreadSubscribeType = "meshagent.chat.thread.subscribe";
443
+ exports.messagingChatThreadListSubscribeType = "meshagent.chat.thread_list.subscribe";
444
+ class ThreadSubscribe {
445
+ constructor({ threadId, stream }) {
446
+ this.threadId = threadId;
447
+ this.stream = stream;
448
+ }
449
+ get closed() {
450
+ return this.stream.closed;
451
+ }
452
+ async send(message, { attachment } = {}) {
453
+ await this.stream.sendMessage({
454
+ type: agent_messages_js_1.agentRoomMessageType,
455
+ message: message.toJson(),
456
+ attachment,
457
+ });
458
+ }
459
+ async close() {
460
+ await this.stream.close();
461
+ }
462
+ }
463
+ exports.ThreadSubscribe = ThreadSubscribe;
464
+ class ThreadListSubscribe {
465
+ constructor({ stream }) {
466
+ this.stream = stream;
467
+ }
468
+ get closed() {
469
+ return this.stream.closed;
470
+ }
471
+ async close() {
472
+ await this.stream.close();
473
+ }
474
+ }
475
+ exports.ThreadListSubscribe = ThreadListSubscribe;
476
+ function participantWaitAbortedError(reason) {
477
+ if (reason instanceof Error) {
478
+ return reason;
479
+ }
480
+ const error = new Error("Agent participant wait was cancelled.");
481
+ error.name = "AbortError";
482
+ return error;
483
+ }
484
+ class BaseMessagingChatClient extends BaseChatClient {
485
+ constructor({ room, agentName, threadCreatedPendingStartMatcher, deduplicateClientToolRequests = true, }) {
486
+ super({ threadCreatedPendingStartMatcher, deduplicateClientToolRequests });
349
487
  this.pendingParticipantWaits = new Map();
350
488
  this.started = false;
351
489
  this.hasConnected = false;
@@ -442,7 +580,7 @@ class MessagingChatClient extends BaseChatClient {
442
580
  this.attachMessagingListeners();
443
581
  this.room.messaging.start();
444
582
  this.startRoomStatusListener();
445
- await this.room.messaging.enable();
583
+ this.room.messaging.enable();
446
584
  this.waitingForParticipant = true;
447
585
  this.onMessagingChanged();
448
586
  }
@@ -493,7 +631,13 @@ class MessagingChatClient extends BaseChatClient {
493
631
  }
494
632
  return null;
495
633
  }
496
- async waitForAgentParticipant({ waitKey } = {}) {
634
+ async waitForAgentParticipant({ waitKey, signal, timeoutMs, } = {}) {
635
+ if (signal?.aborted) {
636
+ throw participantWaitAbortedError(signal.reason);
637
+ }
638
+ if (timeoutMs != null && (!Number.isFinite(timeoutMs) || timeoutMs < 0)) {
639
+ throw new RangeError("Agent participant wait timeout must be a non-negative finite number.");
640
+ }
497
641
  const existing = this.agentParticipant();
498
642
  if (existing != null) {
499
643
  return existing;
@@ -501,12 +645,34 @@ class MessagingChatClient extends BaseChatClient {
501
645
  const key = waitKey == null || waitKey.trim() === "" ? (0, uuid_1.v4)() : waitKey.trim();
502
646
  const completer = new meshagent_1.Completer();
503
647
  this.pendingParticipantWaits.set(key, completer);
648
+ const handleAbort = () => {
649
+ if (!completer.completed) {
650
+ completer.completeError(participantWaitAbortedError(signal?.reason));
651
+ }
652
+ };
653
+ signal?.addEventListener("abort", handleAbort, { once: true });
654
+ if (signal?.aborted) {
655
+ handleAbort();
656
+ }
657
+ const timeout = timeoutMs == null
658
+ ? undefined
659
+ : setTimeout(() => {
660
+ if (!completer.completed) {
661
+ completer.completeError(new Error(`Agent messaging participant was not available within ${timeoutMs}ms.`));
662
+ }
663
+ }, timeoutMs);
504
664
  this.onMessagingChanged();
505
665
  try {
506
666
  return await completer.fut;
507
667
  }
508
668
  finally {
509
- this.pendingParticipantWaits.delete(key);
669
+ signal?.removeEventListener("abort", handleAbort);
670
+ if (timeout != null) {
671
+ clearTimeout(timeout);
672
+ }
673
+ if (this.pendingParticipantWaits.get(key) === completer) {
674
+ this.pendingParticipantWaits.delete(key);
675
+ }
510
676
  }
511
677
  }
512
678
  async sendAgentMessage(message, { attachment } = {}) {
@@ -560,6 +726,372 @@ class MessagingChatClient extends BaseChatClient {
560
726
  }
561
727
  }
562
728
  }
729
+ exports.BaseMessagingChatClient = BaseMessagingChatClient;
730
+ class WebSocketChatClient extends BaseChatClient {
731
+ constructor({ url, token, participantName, protocols = ["meshagent-msgpack"], reconnect = true, reconnectInitialDelay = 1000, reconnectMaxDelay = 10000, }) {
732
+ super({ deduplicateClientToolRequests: true });
733
+ this.started = false;
734
+ this.stopping = false;
735
+ this.connecting = false;
736
+ this.reconnectAttempts = 0;
737
+ this.onMessage = (event) => {
738
+ try {
739
+ const bytes = webSocketMessageBytes(event.data);
740
+ if (bytes == null) {
741
+ return;
742
+ }
743
+ const decoded = (0, msgpack_1.decode)(bytes);
744
+ if (!isJsonMap(decoded)) {
745
+ throw new Error("chat websocket received a non-object message");
746
+ }
747
+ const message = agent_messages_js_1.AgentMessage.fromJson(decoded);
748
+ if (message instanceof agent_messages_js_1.AgentConnectionStatus) {
749
+ const participantId = message.participantId?.trim();
750
+ if (participantId != null && participantId !== "") {
751
+ this.assignedParticipantId = participantId;
752
+ }
753
+ }
754
+ this.handleAgentMessage(message);
755
+ }
756
+ catch (error) {
757
+ this.receiveError = error;
758
+ this.emitConnectionStatus({
759
+ status: "disconnected",
760
+ message: "Chat websocket message could not be decoded",
761
+ reason: describeError(error),
762
+ });
763
+ this.webSocket?.close(1003);
764
+ }
765
+ };
766
+ this.onSocketError = (event) => {
767
+ this.receiveError = event.error ?? new Error("chat websocket error");
768
+ };
769
+ this.onSocketClose = (event) => {
770
+ const webSocket = this.webSocket;
771
+ if (webSocket == null) {
772
+ return;
773
+ }
774
+ this.closeCode = event.code;
775
+ this.closeReason = event.reason;
776
+ this.detachSocketListeners(webSocket);
777
+ this.webSocket = undefined;
778
+ this.assignedParticipantId = undefined;
779
+ if (this.stopping || !this.started) {
780
+ this.notifyListeners();
781
+ return;
782
+ }
783
+ const reason = event.reason !== "" ? `code=${event.code}: ${event.reason}` : `code=${event.code}`;
784
+ if (this.reconnect) {
785
+ this.scheduleReconnect({ reason });
786
+ }
787
+ else {
788
+ this.emitConnectionStatus({
789
+ status: "disconnected",
790
+ message: "Chat websocket disconnected",
791
+ reason,
792
+ });
793
+ }
794
+ this.notifyListeners();
795
+ };
796
+ this.url = url;
797
+ this.token = token;
798
+ this.participantName = participantName;
799
+ this.protocols = protocols;
800
+ this.reconnect = reconnect;
801
+ this.reconnectInitialDelay = reconnectInitialDelay;
802
+ this.reconnectMaxDelay = reconnectMaxDelay;
803
+ }
804
+ get isConnected() {
805
+ return this.webSocket != null && this.webSocket.readyState === isomorphic_ws_1.default.OPEN;
806
+ }
807
+ localParticipantName() {
808
+ return this.cleanParticipantName(this.participantName);
809
+ }
810
+ localParticipantId() {
811
+ return this.assignedParticipantId;
812
+ }
813
+ async start() {
814
+ this.started = true;
815
+ this.stopping = false;
816
+ if (this.webSocket != null || this.connecting) {
817
+ return;
818
+ }
819
+ await this.connect({ isReconnect: false });
820
+ }
821
+ async connect({ isReconnect }) {
822
+ if (this.webSocket != null || this.connecting || !this.started || this.stopping) {
823
+ return;
824
+ }
825
+ this.connecting = true;
826
+ const webSocket = new isomorphic_ws_1.default(this.url.toString(), this.resolvedProtocols());
827
+ this.webSocket = webSocket;
828
+ this.assignedParticipantId = undefined;
829
+ webSocket.binaryType = "arraybuffer";
830
+ try {
831
+ await new Promise((resolve, reject) => {
832
+ const onOpen = () => {
833
+ cleanup();
834
+ resolve();
835
+ };
836
+ const onError = (event) => {
837
+ cleanup();
838
+ reject(event.error ?? new Error("chat websocket connection failed"));
839
+ };
840
+ const cleanup = () => {
841
+ webSocket.removeEventListener("open", onOpen);
842
+ webSocket.removeEventListener("error", onError);
843
+ };
844
+ webSocket.addEventListener("open", onOpen);
845
+ webSocket.addEventListener("error", onError);
846
+ });
847
+ }
848
+ catch (error) {
849
+ if (this.webSocket === webSocket) {
850
+ this.webSocket = undefined;
851
+ }
852
+ this.receiveError = error;
853
+ this.connecting = false;
854
+ if (isReconnect && this.reconnect && !this.stopping) {
855
+ this.scheduleReconnect({ reason: describeError(error) });
856
+ return;
857
+ }
858
+ this.emitConnectionStatus({
859
+ status: "disconnected",
860
+ message: "Chat websocket connection failed",
861
+ reason: describeError(error),
862
+ });
863
+ throw error;
864
+ }
865
+ webSocket.addEventListener("message", this.onMessage);
866
+ webSocket.addEventListener("error", this.onSocketError);
867
+ webSocket.addEventListener("close", this.onSocketClose);
868
+ this.connecting = false;
869
+ this.receiveError = undefined;
870
+ this.closeCode = undefined;
871
+ this.closeReason = undefined;
872
+ const status = isReconnect ? "reconnected" : "connected";
873
+ this.emitConnectionStatus({
874
+ status,
875
+ message: isReconnect ? "Chat websocket reconnected" : "Chat websocket connected",
876
+ });
877
+ if (isReconnect) {
878
+ await this.reopenOpenSessions();
879
+ }
880
+ this.reconnectAttempts = 0;
881
+ this.notifyListeners();
882
+ }
883
+ async stop() {
884
+ this.started = false;
885
+ this.stopping = true;
886
+ if (this.reconnectTimer != null) {
887
+ clearTimeout(this.reconnectTimer);
888
+ this.reconnectTimer = undefined;
889
+ }
890
+ const webSocket = this.webSocket;
891
+ this.webSocket = undefined;
892
+ this.assignedParticipantId = undefined;
893
+ if (webSocket != null) {
894
+ this.detachSocketListeners(webSocket);
895
+ webSocket.close(1000);
896
+ }
897
+ this.emitConnectionStatus({
898
+ status: "disconnected",
899
+ message: "Chat websocket disconnected",
900
+ reason: "client_stopped",
901
+ });
902
+ this.stopping = false;
903
+ this.notifyListeners();
904
+ }
905
+ async sendAgentMessage(message, { attachment } = {}) {
906
+ if (attachment != null) {
907
+ throw new Error("WebSocketChatClient does not support binary attachments yet.");
908
+ }
909
+ const webSocket = this.webSocket;
910
+ if (webSocket == null || webSocket.readyState !== isomorphic_ws_1.default.OPEN) {
911
+ throw new Error(this.closedMessage());
912
+ }
913
+ webSocket.send((0, msgpack_1.encode)(message.toJson()));
914
+ }
915
+ detachSocketListeners(webSocket) {
916
+ webSocket.removeEventListener("message", this.onMessage);
917
+ webSocket.removeEventListener("error", this.onSocketError);
918
+ webSocket.removeEventListener("close", this.onSocketClose);
919
+ }
920
+ scheduleReconnect({ reason }) {
921
+ if (this.reconnectTimer != null || this.stopping || !this.started) {
922
+ return;
923
+ }
924
+ const retryDelay = this.nextReconnectDelay();
925
+ this.emitConnectionStatus({
926
+ status: "reconnecting",
927
+ message: "Chat websocket disconnected; reconnecting",
928
+ reason,
929
+ retryDelay,
930
+ });
931
+ this.reconnectTimer = setTimeout(() => {
932
+ this.reconnectTimer = undefined;
933
+ void this.connect({ isReconnect: true });
934
+ }, retryDelay);
935
+ }
936
+ nextReconnectDelay() {
937
+ const initialDelay = Math.max(1, this.reconnectInitialDelay);
938
+ const maxDelay = Math.max(initialDelay, this.reconnectMaxDelay);
939
+ const factor = 2 ** Math.min(this.reconnectAttempts, 6);
940
+ this.reconnectAttempts += 1;
941
+ return Math.min(initialDelay * factor, maxDelay);
942
+ }
943
+ async reopenOpenSessions() {
944
+ for (const session of this.sessions) {
945
+ if (!session.isOpen) {
946
+ continue;
947
+ }
948
+ await session.open({ load: true, sinceTurn: session.lastCompletedTurnId });
949
+ }
950
+ }
951
+ resolvedProtocols() {
952
+ const resolved = [];
953
+ for (const protocol of this.protocols) {
954
+ const normalized = protocol.trim();
955
+ if (normalized !== "" && !resolved.includes(normalized)) {
956
+ resolved.push(normalized);
957
+ }
958
+ }
959
+ const normalizedToken = this.token.trim();
960
+ if (normalizedToken !== "") {
961
+ resolved.push(`meshagent-agent.${normalizedToken}`);
962
+ }
963
+ return resolved;
964
+ }
965
+ closedMessage() {
966
+ if (this.receiveError != null) {
967
+ return `chat websocket is closed: ${describeError(this.receiveError)}`;
968
+ }
969
+ if (this.closeCode != null) {
970
+ return `chat websocket is closed (code=${this.closeCode})`;
971
+ }
972
+ if (this.closeReason != null && this.closeReason.trim() !== "") {
973
+ return `chat websocket is closed: ${this.closeReason}`;
974
+ }
975
+ return "chat websocket is closed";
976
+ }
977
+ }
978
+ exports.WebSocketChatClient = WebSocketChatClient;
979
+ class MessagingChatClient extends BaseMessagingChatClient {
980
+ constructor() {
981
+ super(...arguments);
982
+ this.threadSubscriptions = new Map();
983
+ this.streamTasks = new Set();
984
+ }
985
+ async stop() {
986
+ const subscriptions = [
987
+ ...this.threadSubscriptions.values(),
988
+ ];
989
+ if (this.threadListSubscription != null) {
990
+ subscriptions.push(this.threadListSubscription);
991
+ }
992
+ this.threadSubscriptions.clear();
993
+ this.threadListSubscription = undefined;
994
+ await Promise.all(subscriptions.map(async (subscription) => subscription.close()));
995
+ await Promise.all(this.streamTasks);
996
+ await super.stop();
997
+ }
998
+ supportsThreadSubscriptions(participant) {
999
+ return participant.getAttribute("supports_messaging_streams") === true;
1000
+ }
1001
+ trackStream(subscription) {
1002
+ const task = (async () => {
1003
+ try {
1004
+ for await (const event of subscription.stream) {
1005
+ if (event.kind !== "message" || event.message.type !== agent_messages_js_1.agentRoomMessageType) {
1006
+ continue;
1007
+ }
1008
+ const raw = event.message.message;
1009
+ if (typeof raw["type"] !== "string") {
1010
+ continue;
1011
+ }
1012
+ this.handleAgentMessage(agent_messages_js_1.AgentMessage.fromJson(raw), {
1013
+ createdAt: dateOrNull(raw["created_at"]),
1014
+ attachment: event.message.attachment,
1015
+ });
1016
+ }
1017
+ }
1018
+ finally {
1019
+ if (subscription instanceof ThreadSubscribe) {
1020
+ if (this.threadSubscriptions.get(subscription.threadId) === subscription) {
1021
+ this.threadSubscriptions.delete(subscription.threadId);
1022
+ }
1023
+ }
1024
+ else if (this.threadListSubscription === subscription) {
1025
+ this.threadListSubscription = undefined;
1026
+ }
1027
+ }
1028
+ })();
1029
+ this.streamTasks.add(task);
1030
+ void task.finally(() => this.streamTasks.delete(task));
1031
+ }
1032
+ async sendAgentMessage(message, { attachment } = {}) {
1033
+ await this.start();
1034
+ const participant = this.agentParticipant();
1035
+ if (participant == null) {
1036
+ throw new Error("Agent messaging participant is not available.");
1037
+ }
1038
+ if (!this.supportsThreadSubscriptions(participant)) {
1039
+ await super.sendAgentMessage(message, { attachment });
1040
+ return;
1041
+ }
1042
+ if (message instanceof agent_messages_js_1.OpenThread) {
1043
+ const previous = this.threadSubscriptions.get(message.threadId);
1044
+ if (previous != null) {
1045
+ await previous.close();
1046
+ }
1047
+ const stream = await this.room.messaging.stream({
1048
+ to: participant,
1049
+ type: exports.messagingChatThreadSubscribeType,
1050
+ message: message.toJson(),
1051
+ attachment,
1052
+ });
1053
+ const subscription = new ThreadSubscribe({ threadId: message.threadId, stream });
1054
+ this.threadSubscriptions.set(message.threadId, subscription);
1055
+ this.trackStream(subscription);
1056
+ return;
1057
+ }
1058
+ if (message instanceof agent_messages_js_1.CloseThread) {
1059
+ const subscription = this.threadSubscriptions.get(message.threadId);
1060
+ if (subscription != null) {
1061
+ this.threadSubscriptions.delete(message.threadId);
1062
+ await subscription.close();
1063
+ return;
1064
+ }
1065
+ }
1066
+ if (message instanceof agent_messages_js_1.WatchThreads) {
1067
+ await this.threadListSubscription?.close();
1068
+ const stream = await this.room.messaging.stream({
1069
+ to: participant,
1070
+ type: exports.messagingChatThreadListSubscribeType,
1071
+ message: message.toJson(),
1072
+ attachment,
1073
+ });
1074
+ const subscription = new ThreadListSubscribe({ stream });
1075
+ this.threadListSubscription = subscription;
1076
+ this.trackStream(subscription);
1077
+ return;
1078
+ }
1079
+ if (message instanceof agent_messages_js_1.UnwatchThreads && this.threadListSubscription != null) {
1080
+ const subscription = this.threadListSubscription;
1081
+ this.threadListSubscription = undefined;
1082
+ await subscription.close();
1083
+ return;
1084
+ }
1085
+ if ("threadId" in message && typeof message.threadId === "string") {
1086
+ const subscription = this.threadSubscriptions.get(message.threadId);
1087
+ if (subscription != null) {
1088
+ await subscription.send(message, { attachment });
1089
+ return;
1090
+ }
1091
+ }
1092
+ await super.sendAgentMessage(message, { attachment });
1093
+ }
1094
+ }
563
1095
  exports.MessagingChatClient = MessagingChatClient;
564
1096
  function isThreadListMessage(message) {
565
1097
  return message.type === agent_messages_js_1.agentThreadListedType
@@ -583,6 +1115,9 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
583
1115
  this.client = client;
584
1116
  this.threadPath = threadPath;
585
1117
  }
1118
+ static create({ client, threadPath }) {
1119
+ return new ChatThreadSession({ client, threadPath });
1120
+ }
586
1121
  get messages() {
587
1122
  return [...this._messages];
588
1123
  }
@@ -601,18 +1136,6 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
601
1136
  get lastCompletedTurnId() {
602
1137
  return this.lastCompletedTurnIdValue;
603
1138
  }
604
- get activeTurnId() {
605
- return this.activeTurnIdValue;
606
- }
607
- get threadStatus() {
608
- return this.threadStatusValue;
609
- }
610
- get currentModel() {
611
- return this.currentModelValue;
612
- }
613
- get modelsResponse() {
614
- return this.modelsResponseValue;
615
- }
616
1139
  async open({ load = true, sinceTurn } = {}) {
617
1140
  if (this.openState) {
618
1141
  if (load) {
@@ -627,7 +1150,6 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
627
1150
  }
628
1151
  catch (error) {
629
1152
  this.setLoadState(this.failedLoadState(error));
630
- throw error;
631
1153
  }
632
1154
  }
633
1155
  return;
@@ -646,7 +1168,6 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
646
1168
  }
647
1169
  catch (error) {
648
1170
  this.setLoadState(this.failedLoadState(error));
649
- throw error;
650
1171
  }
651
1172
  }
652
1173
  resetReplayState() {
@@ -693,16 +1214,20 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
693
1214
  response,
694
1215
  }));
695
1216
  }
696
- async sendText({ messageId, text, attachments, steer = false, turnId, backend, provider, model, voice, outputModalities, senderName, clientToolkits, toolChoice, }) {
1217
+ claimClientToolCall(requestId) {
1218
+ return this.client.claimClientToolRequest(this.threadPath, requestId);
1219
+ }
1220
+ finishClientToolCall(requestId, { responseSent }) {
1221
+ this.client.finishClientToolRequest(this.threadPath, requestId, { responseSent });
1222
+ }
1223
+ injectMessages(messages) {
1224
+ return this.client.sendAgentMessage(new agent_messages_js_1.InjectMessages({
1225
+ threadId: this.threadPath,
1226
+ messages: [...messages],
1227
+ }));
1228
+ }
1229
+ async sendText({ messageId, text, attachments, steer = false, turnId, backend, provider, model, voice, outputModalities, senderName, clientToolkits, }) {
697
1230
  const resolvedMessageId = messageId == null || messageId.trim() === "" ? (0, uuid_1.v4)() : messageId.trim();
698
- const currentModel = this.currentModelValue;
699
- const resolvedBackend = nonEmptyTrimmed(backend) ?? currentModel?.backend;
700
- const resolvedProvider = nonEmptyTrimmed(provider) ?? currentModel?.provider;
701
- const resolvedModel = nonEmptyTrimmed(model) ?? currentModel?.model;
702
- const resolvedVoice = nonEmptyTrimmed(voice) ?? currentModel?.voice;
703
- const resolvedOutputModalities = outputModalities != null && outputModalities.length > 0
704
- ? outputModalities
705
- : currentModel?.outputModalities;
706
1231
  const payload = steer
707
1232
  ? new agent_messages_js_1.TurnSteer({
708
1233
  threadId: this.threadPath,
@@ -716,13 +1241,12 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
716
1241
  messageId: resolvedMessageId,
717
1242
  senderName: nonEmptyTrimmed(senderName),
718
1243
  content: (0, agent_messages_js_1.agentInputContent)({ text, attachments }),
719
- backend: resolvedBackend,
720
- provider: resolvedProvider,
721
- model: resolvedModel,
722
- voice: resolvedVoice,
723
- outputModalities: resolvedOutputModalities,
1244
+ backend: nonEmptyTrimmed(backend),
1245
+ provider: nonEmptyTrimmed(provider),
1246
+ model: nonEmptyTrimmed(model),
1247
+ voice: nonEmptyTrimmed(voice),
1248
+ outputModalities: outputModalities != null && outputModalities.length > 0 ? outputModalities : undefined,
724
1249
  clientToolkits: clientToolkits != null && clientToolkits.length > 0 ? clientToolkits : undefined,
725
- toolChoice: toolChoice?.toJson(),
726
1250
  });
727
1251
  this.localAgentMessageIds.add(resolvedMessageId);
728
1252
  this.pendingLocalInputMessageIds.add(resolvedMessageId);
@@ -741,10 +1265,10 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
741
1265
  await this.client.sendAgentMessage(new agent_messages_js_1.AgentRealtimeAudioChunk({
742
1266
  threadId: this.threadPath,
743
1267
  messageId: (0, uuid_1.v4)(),
744
- format,
1268
+ format: new agent_messages_js_1.AgentAudioFormat(format),
745
1269
  }), { attachment: chunk });
746
1270
  }
747
- async commitRealtimeAudio({ turnId, provider, model, voice, outputModalities, }) {
1271
+ async commitRealtimeAudio({ turnId, backend, provider, model, voice, outputModalities, }) {
748
1272
  const messageId = (0, uuid_1.v4)();
749
1273
  await this.client.sendAgentMessage(new agent_messages_js_1.AgentRealtimeAudioCommit({
750
1274
  threadId: this.threadPath,
@@ -755,6 +1279,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
755
1279
  threadId: this.threadPath,
756
1280
  messageId: (0, uuid_1.v4)(),
757
1281
  turnId,
1282
+ backend: nonEmptyTrimmed(backend),
758
1283
  provider: nonEmptyTrimmed(provider),
759
1284
  model: nonEmptyTrimmed(model),
760
1285
  voice: nonEmptyTrimmed(voice),
@@ -783,56 +1308,9 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
783
1308
  const turnId = normalizedString(threadMessageValue(message, "turnId"));
784
1309
  if (turnId != null) {
785
1310
  this.lastCompletedTurnIdValue = turnId;
786
- if (this.activeTurnIdValue === turnId) {
787
- this.activeTurnIdValue = undefined;
788
- }
789
- }
790
- const statusTurnId = normalizedString(this.threadStatusValue?.turnId);
791
- if (statusTurnId == null || statusTurnId === turnId) {
792
- this.threadStatusValue = undefined;
793
1311
  }
794
- return;
795
1312
  }
796
- if (message.type === agent_messages_js_1.agentTurnStartAcceptedType || message.type === agent_messages_js_1.agentTurnStartedType) {
797
- const turnId = normalizedString(threadMessageValue(message, "turnId"));
798
- if (turnId != null) {
799
- this.activeTurnIdValue = turnId;
800
- }
801
- if (message.type === agent_messages_js_1.agentTurnStartedType) {
802
- const statusTurnId = normalizedString(this.threadStatusValue?.turnId);
803
- if (statusTurnId == null || statusTurnId === turnId) {
804
- this.threadStatusValue = undefined;
805
- }
806
- }
807
- return;
808
- }
809
- if (message.type === agent_messages_js_1.agentThreadStatusType && message instanceof agent_messages_js_1.AgentThreadStatus) {
810
- const mode = normalizedString(message.mode);
811
- const status = normalizedString(message.status);
812
- const turnId = normalizedString(message.turnId);
813
- if (status == null) {
814
- this.threadStatusValue = undefined;
815
- if (turnId != null && this.activeTurnIdValue === turnId) {
816
- this.activeTurnIdValue = undefined;
817
- }
818
- return;
819
- }
820
- this.threadStatusValue = message;
821
- if (mode === "steerable" && turnId != null) {
822
- this.activeTurnIdValue = turnId;
823
- }
824
- return;
825
- }
826
- if (message.type === agent_messages_js_1.agentModelChangedType && message instanceof agent_messages_js_1.AgentModelChanged) {
827
- this.currentModelValue = message;
828
- return;
829
- }
830
- if (message.type === agent_messages_js_1.agentModelsResponseType && message instanceof agent_messages_js_1.ModelsResponse) {
831
- this.modelsResponseValue = message;
832
- this.applyActiveModel(message);
833
- return;
834
- }
835
- if (message.type === agent_messages_js_1.agentThreadLoadedType) {
1313
+ else if (message.type === agent_messages_js_1.agentThreadLoadedType) {
836
1314
  this.setLoadState(new ChatThreadSessionLoadState({
837
1315
  phase: ChatThreadSessionLoadPhase.Loaded,
838
1316
  startedAt: this.loadStateValue.startedAt,
@@ -910,45 +1388,21 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
910
1388
  }
911
1389
  appendRenderableMessage(event) {
912
1390
  const message = event.message;
913
- if (message.type === agent_messages_js_1.agentTurnEndedType) {
914
- if (message.error != null) {
915
- this.appendMessage(event);
916
- }
917
- return;
918
- }
919
- if (message.type === agent_messages_js_1.agentToolCallEndedType) {
920
- const itemId = message.error == null ? undefined : normalizedString(message.itemId);
921
- if (itemId != null) {
922
- this.upsertItemMessage(`tool_call:${itemId}`, event);
923
- }
924
- else if (message.error != null) {
925
- this.appendMessage(event);
926
- }
927
- return;
928
- }
929
- if (message.type === agent_messages_js_1.agentToolCallPendingType || message.type === agent_messages_js_1.agentToolCallInProgressType || message.type === agent_messages_js_1.agentToolCallStartedType) {
930
- const itemId = normalizedString(message.itemId);
931
- if (itemId != null) {
932
- this.upsertItemMessage(`tool_call:${itemId}`, event);
933
- }
934
- return;
935
- }
936
- if (message.type === agent_messages_js_1.agentSecretRequestedType) {
937
- this.appendMessage(event);
938
- return;
939
- }
940
- if (message.type === agent_messages_js_1.agentModelChangedType) {
1391
+ if (message instanceof agent_messages_js_1.TurnEnded) {
941
1392
  this.appendMessage(event);
942
1393
  return;
943
1394
  }
944
- if (message.type === agent_messages_js_1.agentThreadStartType || message.type === agent_messages_js_1.agentTurnStartType || message.type === agent_messages_js_1.agentTurnSteerType) {
945
- if (agentInputText(message.content).trim() !== "") {
1395
+ if (message instanceof agent_messages_js_1.StartThread || message instanceof agent_messages_js_1.TurnStart || message instanceof agent_messages_js_1.TurnSteer) {
1396
+ if (agentInputText(messageValue(message, "content")).trim() !== "") {
946
1397
  this.appendMessage(event);
1398
+ const messageId = normalizedString(message.messageId);
1399
+ if (messageId != null)
1400
+ this.pendingLocalInputMessageIds.add(messageId);
947
1401
  }
948
1402
  return;
949
1403
  }
950
- if (message.type === agent_messages_js_1.agentTurnStartAcceptedType || message.type === agent_messages_js_1.agentTurnSteerAcceptedType) {
951
- const sourceMessageId = normalizedString(sourceMessageIdFor(message));
1404
+ if (message instanceof agent_messages_js_1.TurnStartAccepted) {
1405
+ const sourceMessageId = normalizedString(message.sourceMessageId);
952
1406
  if (sourceMessageId != null && this.localAgentMessageIds.has(sourceMessageId)) {
953
1407
  this.pendingLocalInputMessageIds.delete(sourceMessageId);
954
1408
  return;
@@ -956,36 +1410,21 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
956
1410
  if (agentInputText(message.content).trim() !== "") {
957
1411
  this.appendMessage(event, { beforePendingLocalInputs: true });
958
1412
  }
959
- else {
960
- this.appendMessage(event);
961
- }
962
- return;
963
- }
964
- if (message.type === agent_messages_js_1.agentTurnStartedType ||
965
- message.type === agent_messages_js_1.agentTurnSteeredType ||
966
- message.type === agent_messages_js_1.agentTurnStartRejectedType ||
967
- message.type === agent_messages_js_1.agentTurnSteerRejectedType ||
968
- message.type === agent_messages_js_1.agentTurnInterruptAcceptedType ||
969
- message.type === agent_messages_js_1.agentTurnInterruptedType) {
970
- this.appendMessage(event);
971
1413
  return;
972
1414
  }
973
1415
  if (isMergeableDelta(message)) {
974
1416
  this.appendOrMergeDelta(event);
975
1417
  return;
976
1418
  }
977
- if (message.type === agent_messages_js_1.agentImageGenerationPartialType || message.type === agent_messages_js_1.agentImageGenerationCompletedType) {
978
- const itemId = normalizedString(message.itemId);
979
- if (itemId != null) {
980
- this.upsertItemMessage(`image_generation:${itemId}`, event);
981
- }
1419
+ if (message instanceof agent_messages_js_1.AgentImageGenerationPartial || message instanceof agent_messages_js_1.AgentImageGenerationCompleted) {
1420
+ this.appendMessage(event);
982
1421
  return;
983
1422
  }
984
- if (message.type === agent_messages_js_1.agentUsageUpdatedType) {
1423
+ if (message instanceof agent_messages_js_1.AgentClientToolCallRequested) {
985
1424
  this.appendMessage(event);
986
1425
  return;
987
1426
  }
988
- if (message instanceof agent_messages_js_1.AgentClientToolCallRequested) {
1427
+ if (message instanceof agent_messages_js_1.AgentConnectionStatus || message instanceof agent_messages_js_1.AgentThreadMessage) {
989
1428
  this.appendMessage(event);
990
1429
  }
991
1430
  }
@@ -1005,15 +1444,6 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
1005
1444
  this.messageIndexes.set(normalizedMessageId, this._messages.length);
1006
1445
  this._messages.push(event);
1007
1446
  }
1008
- upsertItemMessage(key, event) {
1009
- const existingIndex = this.messageIndexes.get(key);
1010
- if (existingIndex == null) {
1011
- this.messageIndexes.set(key, this._messages.length);
1012
- this._messages.push(event);
1013
- return;
1014
- }
1015
- this._messages[existingIndex] = event;
1016
- }
1017
1447
  appendOrMergeDelta(event) {
1018
1448
  const message = event.message;
1019
1449
  const normalizedMessageId = normalizedString(message.messageId);
@@ -1023,7 +1453,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
1023
1453
  }
1024
1454
  this.mergedDeltaMessageIds.add(normalizedMessageId);
1025
1455
  }
1026
- const itemId = normalizedString(message.itemId);
1456
+ const itemId = normalizedString(messageValue(message, "itemId"));
1027
1457
  if (itemId == null) {
1028
1458
  return;
1029
1459
  }
@@ -1037,7 +1467,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
1037
1467
  const existing = this._messages[existingIndex].message;
1038
1468
  const merged = mergeDeltaMessage(existing, message);
1039
1469
  if (merged != null) {
1040
- this._messages[existingIndex] = new AgentMessageEvent({ message: merged, createdAt: event.createdAt, attachment: event.attachment });
1470
+ this._messages[existingIndex].replaceMessage(merged);
1041
1471
  }
1042
1472
  }
1043
1473
  indexMessagesFrom(start) {
@@ -1048,29 +1478,6 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
1048
1478
  }
1049
1479
  }
1050
1480
  }
1051
- applyActiveModel(response) {
1052
- for (const provider of response.providers) {
1053
- for (const model of provider.models) {
1054
- if (!model.active) {
1055
- continue;
1056
- }
1057
- this.currentModelValue = new agent_messages_js_1.AgentModelChanged({
1058
- threadId: this.threadPath,
1059
- sourceMessageId: response.sourceMessageId,
1060
- backend: provider.backend,
1061
- provider: provider.name,
1062
- model: model.name,
1063
- voice: model.defaultOutputVoice,
1064
- inputFormat: model.inputFormat,
1065
- outputFormat: model.outputFormat,
1066
- turnDetection: model.turnDetection,
1067
- realtimeProtocols: model.realtimeProtocols,
1068
- outputModalities: model.modalities.length > 0 ? [model.modalities[0]] : ["text"],
1069
- });
1070
- return;
1071
- }
1072
- }
1073
- }
1074
1481
  markClosed({ notify = true } = {}) {
1075
1482
  this.openState = false;
1076
1483
  this.loadStateValue = new ChatThreadSessionLoadState({
@@ -1130,12 +1537,33 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
1130
1537
  }
1131
1538
  }
1132
1539
  exports.ChatThreadSession = ChatThreadSession;
1540
+ function webSocketMessageBytes(value) {
1541
+ if (value instanceof Uint8Array) {
1542
+ return value;
1543
+ }
1544
+ if (value instanceof ArrayBuffer) {
1545
+ return new Uint8Array(value);
1546
+ }
1547
+ if (ArrayBuffer.isView(value)) {
1548
+ return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
1549
+ }
1550
+ return undefined;
1551
+ }
1552
+ function isJsonMap(value) {
1553
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1554
+ }
1555
+ function describeError(error) {
1556
+ return error instanceof Error ? error.message : String(error);
1557
+ }
1133
1558
  function sourceMessageIdFor(message) {
1134
1559
  const value = "sourceMessageId" in message ? message.sourceMessageId : undefined;
1135
1560
  return typeof value === "string" ? value : undefined;
1136
1561
  }
1562
+ function messageValue(message, key) {
1563
+ return message[key];
1564
+ }
1137
1565
  function threadMessageValue(message, key) {
1138
- const value = message[key];
1566
+ const value = messageValue(message, key);
1139
1567
  return typeof value === "string" ? value : undefined;
1140
1568
  }
1141
1569
  function agentInputText(content) {
@@ -1163,7 +1591,7 @@ function isMergeableDelta(message) {
1163
1591
  }
1164
1592
  function messageIndexKey(message) {
1165
1593
  if (isMergeableDelta(message)) {
1166
- const itemId = normalizedString(message.itemId);
1594
+ const itemId = normalizedString(messageValue(message, "itemId"));
1167
1595
  return itemId == null ? undefined : `${message.type}:${itemId}`;
1168
1596
  }
1169
1597
  return normalizedString(message.messageId);
@@ -1176,30 +1604,30 @@ function mergeDeltaMessage(existing, incoming) {
1176
1604
  const data = new Uint8Array(existing.data.length + incoming.data.length);
1177
1605
  data.set(existing.data, 0);
1178
1606
  data.set(incoming.data, existing.data.length);
1179
- return new agent_messages_js_1.AgentAudioGenerationDelta({ ...existing.toJson(), data });
1607
+ return agent_messages_js_1.AgentAudioGenerationDelta.fromJson({ ...existing.toJson(), data });
1180
1608
  }
1181
1609
  if (existing.type === agent_messages_js_1.agentAudioTranscriptionDeltaType && existing instanceof agent_messages_js_1.AgentAudioTranscriptionDelta && incoming instanceof agent_messages_js_1.AgentAudioTranscriptionDelta) {
1182
- return new agent_messages_js_1.AgentAudioTranscriptionDelta({ ...existing.toJson(), text: `${existing.text}${incoming.text}` });
1610
+ return agent_messages_js_1.AgentAudioTranscriptionDelta.fromJson({ ...existing.toJson(), text: `${existing.text}${incoming.text}` });
1183
1611
  }
1184
1612
  if (existing.type === agent_messages_js_1.agentFileContentDeltaType && incoming instanceof agent_messages_js_1.AgentFileContentDelta) {
1185
1613
  return incoming;
1186
1614
  }
1187
1615
  if (existing.type === agent_messages_js_1.agentReasoningContentDeltaType && existing instanceof agent_messages_js_1.AgentReasoningContentDelta && incoming instanceof agent_messages_js_1.AgentReasoningContentDelta) {
1188
- return new agent_messages_js_1.AgentReasoningContentDelta({ ...existing.toJson(), text: `${existing.text}${incoming.text}` });
1616
+ return agent_messages_js_1.AgentReasoningContentDelta.fromJson({ ...existing.toJson(), text: `${existing.text}${incoming.text}` });
1189
1617
  }
1190
1618
  if (existing.type === agent_messages_js_1.agentTextContentDeltaType && existing instanceof agent_messages_js_1.AgentTextContentDelta && incoming instanceof agent_messages_js_1.AgentTextContentDelta) {
1191
- return new agent_messages_js_1.AgentTextContentDelta({ ...existing.toJson(), text: `${existing.text}${incoming.text}` });
1619
+ return agent_messages_js_1.AgentTextContentDelta.fromJson({ ...existing.toJson(), text: `${existing.text}${incoming.text}` });
1192
1620
  }
1193
1621
  if (existing.type === agent_messages_js_1.agentToolCallArgumentsDeltaType && existing instanceof agent_messages_js_1.AgentToolCallArgumentsDelta && incoming instanceof agent_messages_js_1.AgentToolCallArgumentsDelta) {
1194
- return new agent_messages_js_1.AgentToolCallArgumentsDelta({ ...existing.toJson(), delta: `${existing.delta}${incoming.delta}` });
1622
+ return agent_messages_js_1.AgentToolCallArgumentsDelta.fromJson({ ...existing.toJson(), delta: `${existing.delta}${incoming.delta}` });
1195
1623
  }
1196
1624
  if (existing.type === agent_messages_js_1.agentToolCallLogDeltaType && existing instanceof agent_messages_js_1.AgentToolCallLogDelta && incoming instanceof agent_messages_js_1.AgentToolCallLogDelta) {
1197
- return new agent_messages_js_1.AgentToolCallLogDelta({ ...existing.toJson(), lines: [...existing.lines, ...incoming.lines] });
1625
+ return agent_messages_js_1.AgentToolCallLogDelta.fromJson({ ...existing.toJson(), lines: [...existing.lines, ...incoming.lines] });
1198
1626
  }
1199
1627
  return undefined;
1200
1628
  }
1201
1629
  function normalizedString(value) {
1202
- const normalized = value?.trim();
1630
+ const normalized = typeof value === "string" ? value.trim() : undefined;
1203
1631
  return normalized == null || normalized === "" ? undefined : normalized;
1204
1632
  }
1205
1633
  function dateOrNull(value) {