@meshagent/meshagent-agents 0.43.3 → 0.44.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.
@@ -6,12 +6,13 @@ const uuid_1 = require("uuid");
6
6
  const agent_messages_js_1 = require("./agent-messages.js");
7
7
  const change_emitter_js_1 = require("./change-emitter.js");
8
8
  class AgentMessageEvent {
9
- constructor({ message, attachment }) {
9
+ constructor({ message, createdAt, attachment }) {
10
10
  this.message = message;
11
+ this.createdAt = createdAt ?? dateOrNull(message.createdAt) ?? new Date();
11
12
  this.attachment = attachment;
12
13
  }
13
14
  get payload() {
14
- return this.message.toJson();
15
+ return { ...this.message.toJson(), created_at: this.createdAt.toISOString() };
15
16
  }
16
17
  }
17
18
  exports.AgentMessageEvent = AgentMessageEvent;
@@ -203,7 +204,7 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
203
204
  this.notifyListeners();
204
205
  });
205
206
  }
206
- async startThread({ messageId, message, attachments, name, backend, provider, model, voice, outputModalities, realtimeProtocol, senderName, clientToolkits, omitContent = false, }) {
207
+ async startThread({ messageId, message, attachments, name, backend, provider, model, voice, outputModalities, realtimeProtocol, senderName, clientToolkits, toolChoice, omitContent = false, }) {
207
208
  const resolvedMessageId = messageId == null || messageId.trim() === "" ? (0, uuid_1.v4)() : messageId.trim();
208
209
  const resolvedSenderName = this.cleanParticipantName(senderName) ?? this.localParticipantName();
209
210
  const payload = new agent_messages_js_1.StartThread({
@@ -218,6 +219,7 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
218
219
  realtimeProtocol: nonEmptyTrimmed(realtimeProtocol),
219
220
  senderName: resolvedSenderName,
220
221
  clientToolkits: clientToolkits != null && clientToolkits.length > 0 ? clientToolkits : undefined,
222
+ toolChoice: toolChoice?.toJson(),
221
223
  });
222
224
  const completer = new meshagent_1.Completer();
223
225
  this.pendingStartRequests.set(resolvedMessageId, completer);
@@ -232,7 +234,10 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
232
234
  }
233
235
  const session = this.openThread(threadPath, { load: false, drainPendingEvents: false });
234
236
  if (!omitContent) {
235
- session.addAgentMessage(new AgentMessageEvent({ message: payload }));
237
+ session.addAgentMessage(new AgentMessageEvent({
238
+ message: this.resolvedStartThreadMessage({ payload, threadPath }),
239
+ createdAt: dateOrNull(payload.createdAt) ?? undefined,
240
+ }));
236
241
  }
237
242
  this.drainPendingSessionEvents(threadPath, session);
238
243
  return new ChatThreadStartResult({
@@ -247,6 +252,23 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
247
252
  this.pendingStartRequests.delete(resolvedMessageId);
248
253
  }
249
254
  }
255
+ resolvedStartThreadMessage({ payload, threadPath, }) {
256
+ return new agent_messages_js_1.TurnStart({
257
+ threadId: threadPath,
258
+ messageId: payload.messageId,
259
+ senderName: payload.senderName,
260
+ content: payload.content,
261
+ backend: payload.backend,
262
+ provider: payload.provider,
263
+ model: payload.model,
264
+ voice: payload.voice,
265
+ outputModalities: payload.outputModalities,
266
+ instructions: payload.instructions,
267
+ mcp: payload.mcp,
268
+ clientToolkits: payload.clientToolkits,
269
+ toolkits: payload.toolkits,
270
+ });
271
+ }
250
272
  drainPendingSessionEvents(threadPath, session) {
251
273
  const pendingEvents = this.pendingSessionEventsByPath.get(threadPath);
252
274
  if (pendingEvents == null) {
@@ -257,16 +279,16 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
257
279
  session.addAgentMessage(event);
258
280
  }
259
281
  }
260
- handleAgentMessage(message, { attachment } = {}) {
282
+ handleAgentMessage(message, { createdAt, attachment } = {}) {
261
283
  if (message.type === agent_messages_js_1.agentConnectionStatusType) {
262
284
  this._connectionStatus = message;
263
285
  for (const session of this.sessionsByPath.values()) {
264
286
  if (session.isOpen) {
265
- session.addAgentMessage(new AgentMessageEvent({ message, attachment }));
287
+ session.addAgentMessage(new AgentMessageEvent({ message, createdAt, attachment }));
266
288
  }
267
289
  }
268
290
  }
269
- this.eventQueue.add(new AgentMessageEvent({ message, attachment }));
291
+ this.eventQueue.add(new AgentMessageEvent({ message, createdAt, attachment }));
270
292
  const sourceMessageId = sourceMessageIdFor(message);
271
293
  if ((message.type === agent_messages_js_1.agentThreadStartedType || message.type === agent_messages_js_1.agentThreadStartRejectedType) &&
272
294
  sourceMessageId != null &&
@@ -281,7 +303,7 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
281
303
  this.notifyListeners();
282
304
  return;
283
305
  }
284
- const event = new AgentMessageEvent({ message, attachment });
306
+ const event = new AgentMessageEvent({ message, createdAt, attachment });
285
307
  const session = this.sessionsByPath.get(threadPath);
286
308
  if (session != null) {
287
309
  session.addAgentMessage(event);
@@ -344,10 +366,15 @@ class MessagingChatClient extends BaseChatClient {
344
366
  return;
345
367
  }
346
368
  const participant = this.agentParticipant();
347
- if (participant == null || roomMessage.fromParticipantId !== participant.id) {
369
+ const fromSelectedAgent = participant != null && roomMessage.fromParticipantId === participant.id;
370
+ const fromParticipantlessThreadList = roomMessage.fromParticipantId == null && isThreadListMessage(roomMessage.message);
371
+ if (!fromSelectedAgent && !fromParticipantlessThreadList) {
348
372
  return;
349
373
  }
350
- this.handleAgentMessage(agent_messages_js_1.AgentMessage.fromJson(roomMessage.message), { attachment: roomMessage.attachment });
374
+ this.handleAgentMessage(agent_messages_js_1.AgentMessage.fromJson(roomMessage.message), {
375
+ createdAt: dateOrNull(roomMessage.message.created_at),
376
+ attachment: roomMessage.attachment,
377
+ });
351
378
  };
352
379
  this.room = room;
353
380
  this.agentName = agentName;
@@ -416,6 +443,12 @@ class MessagingChatClient extends BaseChatClient {
416
443
  }
417
444
  }
418
445
  exports.MessagingChatClient = MessagingChatClient;
446
+ function isThreadListMessage(message) {
447
+ return message.type === agent_messages_js_1.agentThreadListedType
448
+ || message.type === agent_messages_js_1.agentThreadCreatedType
449
+ || message.type === agent_messages_js_1.agentThreadUpdatedType
450
+ || message.type === agent_messages_js_1.agentThreadDeletedType;
451
+ }
419
452
  class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
420
453
  constructor({ client, threadPath }) {
421
454
  super();
@@ -463,6 +496,9 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
463
496
  async open({ load = true, sinceTurn } = {}) {
464
497
  if (this.openState) {
465
498
  if (load) {
499
+ if (sinceTurn == null) {
500
+ this.resetReplayState();
501
+ }
466
502
  const openThread = new agent_messages_js_1.OpenThread({ threadId: this.threadPath, load: true, sinceTurn });
467
503
  this.setLoadState(this.loadingStateForOpen(openThread, sinceTurn));
468
504
  try {
@@ -493,6 +529,17 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
493
529
  throw error;
494
530
  }
495
531
  }
532
+ resetReplayState() {
533
+ this._messages.length = 0;
534
+ this.messageIndexes.clear();
535
+ this.localAgentMessageIds.clear();
536
+ this.pendingLocalInputMessageIds.clear();
537
+ this.mergedDeltaMessageIds.clear();
538
+ this.pendingInputsById.clear();
539
+ this.lastCompletedTurnIdValue = undefined;
540
+ this.lastAgentMessageType = undefined;
541
+ this.lastAgentMessageAt = undefined;
542
+ }
496
543
  async close() {
497
544
  if (!this.openState) {
498
545
  return;
@@ -524,7 +571,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
524
571
  response,
525
572
  }));
526
573
  }
527
- async sendText({ messageId, text, attachments, steer = false, turnId, backend, provider, model, voice, outputModalities, senderName, clientToolkits, }) {
574
+ async sendText({ messageId, text, attachments, steer = false, turnId, backend, provider, model, voice, outputModalities, senderName, clientToolkits, toolChoice, }) {
528
575
  const resolvedMessageId = messageId == null || messageId.trim() === "" ? (0, uuid_1.v4)() : messageId.trim();
529
576
  const currentModel = this.currentModelValue;
530
577
  const resolvedBackend = nonEmptyTrimmed(backend) ?? currentModel?.backend;
@@ -553,6 +600,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
553
600
  voice: resolvedVoice,
554
601
  outputModalities: resolvedOutputModalities,
555
602
  clientToolkits: clientToolkits != null && clientToolkits.length > 0 ? clientToolkits : undefined,
603
+ toolChoice: toolChoice?.toJson(),
556
604
  });
557
605
  this.localAgentMessageIds.add(resolvedMessageId);
558
606
  this.pendingLocalInputMessageIds.add(resolvedMessageId);
@@ -602,9 +650,9 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
602
650
  const message = event.message;
603
651
  const type = message.type;
604
652
  this.lastAgentMessageType = type;
605
- this.lastAgentMessageAt = new Date();
653
+ this.lastAgentMessageAt = event.createdAt;
606
654
  this.updateSessionState(message);
607
- this.updatePendingInputsForMessage(message);
655
+ this.updatePendingInputsForMessage(message, event.createdAt);
608
656
  this.appendRenderableMessage(event);
609
657
  this.notifyListeners();
610
658
  }
@@ -670,7 +718,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
670
718
  }), { notify: false });
671
719
  }
672
720
  }
673
- updatePendingInputsForMessage(message) {
721
+ updatePendingInputsForMessage(message, createdAt) {
674
722
  const type = message.type;
675
723
  const messageId = message.messageId;
676
724
  const sourceMessageId = sourceMessageIdFor(message);
@@ -684,7 +732,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
684
732
  messageType: type,
685
733
  threadPath: this.threadPath,
686
734
  payload: message,
687
- createdAt: new Date(),
735
+ createdAt,
688
736
  awaitingAcceptance: true,
689
737
  awaitingApplication: true,
690
738
  }));
@@ -723,6 +771,31 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
723
771
  }
724
772
  return;
725
773
  }
774
+ if (message.type === agent_messages_js_1.agentToolCallEndedType) {
775
+ const itemId = normalizedString(message.itemId);
776
+ if (itemId != null) {
777
+ this.upsertItemMessage(`tool_call:${itemId}`, event);
778
+ }
779
+ else if (message.error != null) {
780
+ this.appendMessage(event);
781
+ }
782
+ return;
783
+ }
784
+ if (message.type === agent_messages_js_1.agentToolCallPendingType || message.type === agent_messages_js_1.agentToolCallInProgressType || message.type === agent_messages_js_1.agentToolCallStartedType) {
785
+ const itemId = normalizedString(message.itemId);
786
+ if (itemId != null) {
787
+ this.upsertItemMessage(`tool_call:${itemId}`, event);
788
+ }
789
+ return;
790
+ }
791
+ if (message.type === agent_messages_js_1.agentSecretRequestedType) {
792
+ this.appendMessage(event);
793
+ return;
794
+ }
795
+ if (message.type === agent_messages_js_1.agentModelChangedType) {
796
+ this.appendMessage(event);
797
+ return;
798
+ }
726
799
  if (message.type === agent_messages_js_1.agentThreadStartType || message.type === agent_messages_js_1.agentTurnStartType || message.type === agent_messages_js_1.agentTurnSteerType) {
727
800
  if (agentInputText(message.content).trim() !== "") {
728
801
  this.appendMessage(event);
@@ -738,6 +811,18 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
738
811
  if (agentInputText(message.content).trim() !== "") {
739
812
  this.appendMessage(event, { beforePendingLocalInputs: true });
740
813
  }
814
+ else {
815
+ this.appendMessage(event);
816
+ }
817
+ return;
818
+ }
819
+ if (message.type === agent_messages_js_1.agentTurnStartedType ||
820
+ message.type === agent_messages_js_1.agentTurnSteeredType ||
821
+ message.type === agent_messages_js_1.agentTurnStartRejectedType ||
822
+ message.type === agent_messages_js_1.agentTurnSteerRejectedType ||
823
+ message.type === agent_messages_js_1.agentTurnInterruptAcceptedType ||
824
+ message.type === agent_messages_js_1.agentTurnInterruptedType) {
825
+ this.appendMessage(event);
741
826
  return;
742
827
  }
743
828
  if (isMergeableDelta(message)) {
@@ -751,6 +836,10 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
751
836
  }
752
837
  return;
753
838
  }
839
+ if (message.type === agent_messages_js_1.agentUsageUpdatedType) {
840
+ this.appendMessage(event);
841
+ return;
842
+ }
754
843
  if (message instanceof agent_messages_js_1.AgentClientToolCallRequested) {
755
844
  this.appendMessage(event);
756
845
  }
@@ -803,7 +892,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
803
892
  const existing = this._messages[existingIndex].message;
804
893
  const merged = mergeDeltaMessage(existing, message);
805
894
  if (merged != null) {
806
- this._messages[existingIndex] = new AgentMessageEvent({ message: merged, attachment: event.attachment });
895
+ this._messages[existingIndex] = new AgentMessageEvent({ message: merged, createdAt: event.createdAt, attachment: event.attachment });
807
896
  }
808
897
  }
809
898
  indexMessagesFrom(start) {
@@ -968,6 +1057,16 @@ function normalizedString(value) {
968
1057
  const normalized = value?.trim();
969
1058
  return normalized == null || normalized === "" ? undefined : normalized;
970
1059
  }
1060
+ function dateOrNull(value) {
1061
+ if (value instanceof Date && !Number.isNaN(value.getTime())) {
1062
+ return value;
1063
+ }
1064
+ if (typeof value !== "string" || value.trim() === "") {
1065
+ return undefined;
1066
+ }
1067
+ const parsed = new Date(value);
1068
+ return Number.isNaN(parsed.getTime()) ? undefined : parsed;
1069
+ }
971
1070
  function nonEmptyTrimmed(value) {
972
1071
  const normalized = value?.trim();
973
1072
  return normalized == null || normalized === "" ? undefined : normalized;
@@ -313,10 +313,12 @@ class AgentThreadStorageRepository extends ThreadStorageRepository {
313
313
  this.handleEvent(next.value);
314
314
  }
315
315
  })();
316
- await new Promise((resolve) => {
316
+ const ready = new Promise((resolve) => {
317
317
  this.pendingOpen = { resolve };
318
- void this.requestList();
319
318
  });
319
+ await this.chatClient.sendAgentMessage(new agent_messages_js_1.WatchThreads(), { ignoreOffline: true });
320
+ await this.requestList();
321
+ await ready;
320
322
  }
321
323
  async close() {
322
324
  this.closed = true;
@@ -325,6 +327,7 @@ class AgentThreadStorageRepository extends ThreadStorageRepository {
325
327
  this.pendingListMessageId = undefined;
326
328
  this.pendingOpen?.resolve();
327
329
  this.pendingOpen = undefined;
330
+ await this.chatClient.sendAgentMessage(new agent_messages_js_1.UnwatchThreads(), { ignoreOffline: true }).catch(() => undefined);
328
331
  }
329
332
  entries() {
330
333
  return [...this.entriesByPath.values()];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshagent/meshagent-agents",
3
- "version": "0.43.3",
3
+ "version": "0.44.0",
4
4
  "description": "Agent chat sessions and clients for Meshagent TypeScript applications.",
5
5
  "homepage": "https://github.com/meshagent/meshagent-agents-ts",
6
6
  "scripts": {
@@ -47,7 +47,7 @@
47
47
  "typescript": "^5.8.2"
48
48
  },
49
49
  "dependencies": {
50
- "@meshagent/meshagent": "^0.43.3",
50
+ "@meshagent/meshagent": "^0.44.0",
51
51
  "apache-arrow": "^21.0.0",
52
52
  "uuid": "^14.0.0"
53
53
  },