@meshagent/meshagent-agents 0.43.3 → 0.44.1
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 +14 -0
- package/dist/browser/agent-messages.d.ts +6 -1
- package/dist/browser/agent-messages.js +12 -5
- package/dist/browser/chat-client.d.ts +23 -5
- package/dist/browser/chat-client.js +237 -30
- package/dist/browser/thread-storage.d.ts +1 -0
- package/dist/browser/thread-storage.js +18 -2
- package/dist/esm/agent-messages.d.ts +6 -1
- package/dist/esm/agent-messages.js +8 -1
- package/dist/esm/chat-client.d.ts +23 -5
- package/dist/esm/chat-client.js +238 -31
- package/dist/esm/thread-storage.d.ts +1 -0
- package/dist/esm/thread-storage.js +19 -3
- package/dist/node/agent-messages.d.ts +6 -1
- package/dist/node/agent-messages.js +12 -5
- package/dist/node/chat-client.d.ts +23 -5
- package/dist/node/chat-client.js +237 -30
- package/dist/node/thread-storage.d.ts +1 -0
- package/dist/node/thread-storage.js +18 -2
- package/package.json +2 -2
|
@@ -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({
|
|
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,11 @@ 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
|
-
for (const session of this.sessionsByPath.values()) {
|
|
264
|
-
if (session.isOpen) {
|
|
265
|
-
session.addAgentMessage(new AgentMessageEvent({ message, attachment }));
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
285
|
}
|
|
269
|
-
this.eventQueue.add(new AgentMessageEvent({ message, attachment }));
|
|
286
|
+
this.eventQueue.add(new AgentMessageEvent({ message, createdAt, attachment }));
|
|
270
287
|
const sourceMessageId = sourceMessageIdFor(message);
|
|
271
288
|
if ((message.type === agent_messages_js_1.agentThreadStartedType || message.type === agent_messages_js_1.agentThreadStartRejectedType) &&
|
|
272
289
|
sourceMessageId != null &&
|
|
@@ -281,7 +298,7 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
281
298
|
this.notifyListeners();
|
|
282
299
|
return;
|
|
283
300
|
}
|
|
284
|
-
const event = new AgentMessageEvent({ message, attachment });
|
|
301
|
+
const event = new AgentMessageEvent({ message, createdAt, attachment });
|
|
285
302
|
const session = this.sessionsByPath.get(threadPath);
|
|
286
303
|
if (session != null) {
|
|
287
304
|
session.addAgentMessage(event);
|
|
@@ -302,11 +319,6 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
302
319
|
});
|
|
303
320
|
this._connectionStatus = event;
|
|
304
321
|
this.eventQueue.add(new AgentMessageEvent({ message: event }));
|
|
305
|
-
for (const session of this.sessionsByPath.values()) {
|
|
306
|
-
if (session.isOpen) {
|
|
307
|
-
session.addAgentMessage(new AgentMessageEvent({ message: event }));
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
322
|
this.notifyListeners();
|
|
311
323
|
}
|
|
312
324
|
removeThreadSession(threadPath) {
|
|
@@ -325,10 +337,50 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
325
337
|
super();
|
|
326
338
|
this.pendingParticipantWaits = new Map();
|
|
327
339
|
this.started = false;
|
|
340
|
+
this.hasConnected = false;
|
|
341
|
+
this.waitingForParticipant = false;
|
|
342
|
+
this.messagingListenersAttached = false;
|
|
328
343
|
this.onMessagingChanged = () => {
|
|
329
344
|
const participant = this.agentParticipant();
|
|
345
|
+
const participantId = participant?.id;
|
|
346
|
+
if (participantId !== this.agentParticipantId) {
|
|
347
|
+
if (participantId == null) {
|
|
348
|
+
if (this.agentParticipantId != null) {
|
|
349
|
+
this.waitingForParticipant = true;
|
|
350
|
+
this.emitConnectionStatus({
|
|
351
|
+
status: "disconnected",
|
|
352
|
+
message: "Agent messaging disconnected",
|
|
353
|
+
reason: "participant_disconnected",
|
|
354
|
+
});
|
|
355
|
+
this.emitConnectionStatus({
|
|
356
|
+
status: "reconnecting",
|
|
357
|
+
message: "Waiting for agent messaging",
|
|
358
|
+
reason: "participant_disconnected",
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
else if (this.started && this.waitingForParticipant) {
|
|
362
|
+
this.emitConnectionStatus({
|
|
363
|
+
status: "reconnecting",
|
|
364
|
+
message: "Waiting for agent messaging",
|
|
365
|
+
reason: "participant_offline",
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
const status = this.hasConnected ? "reconnected" : "connected";
|
|
371
|
+
this.hasConnected = true;
|
|
372
|
+
this.waitingForParticipant = false;
|
|
373
|
+
this.emitConnectionStatus({
|
|
374
|
+
status,
|
|
375
|
+
message: status === "reconnected" ? "Agent messaging reconnected" : "Agent messaging connected",
|
|
376
|
+
});
|
|
377
|
+
if (status === "reconnected") {
|
|
378
|
+
void this.reopenOpenSessions();
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
this.agentParticipantId = participantId;
|
|
382
|
+
}
|
|
330
383
|
if (participant != null) {
|
|
331
|
-
this.emitConnectionStatus({ status: "connected", message: "Agent messaging connected" });
|
|
332
384
|
for (const wait of this.pendingParticipantWaits.values()) {
|
|
333
385
|
if (!wait.completed) {
|
|
334
386
|
wait.complete(participant);
|
|
@@ -337,6 +389,12 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
337
389
|
}
|
|
338
390
|
this.notifyListeners();
|
|
339
391
|
};
|
|
392
|
+
this.onMessagingParticipantChanged = () => {
|
|
393
|
+
this.onMessagingChanged();
|
|
394
|
+
};
|
|
395
|
+
this.onMessagingParticipantRemoved = () => {
|
|
396
|
+
this.onMessagingChanged();
|
|
397
|
+
};
|
|
340
398
|
this.onMessagingMessage = (event) => {
|
|
341
399
|
this.onMessagingChanged();
|
|
342
400
|
const roomMessage = agentRoomMessageFromEvent(event);
|
|
@@ -344,14 +402,19 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
344
402
|
return;
|
|
345
403
|
}
|
|
346
404
|
const participant = this.agentParticipant();
|
|
347
|
-
|
|
405
|
+
const fromSelectedAgent = participant != null && roomMessage.fromParticipantId === participant.id;
|
|
406
|
+
const fromParticipantlessThreadList = roomMessage.fromParticipantId == null && isThreadListMessage(roomMessage.message);
|
|
407
|
+
if (!fromSelectedAgent && !fromParticipantlessThreadList) {
|
|
348
408
|
return;
|
|
349
409
|
}
|
|
350
|
-
this.handleAgentMessage(agent_messages_js_1.AgentMessage.fromJson(roomMessage.message), {
|
|
410
|
+
this.handleAgentMessage(agent_messages_js_1.AgentMessage.fromJson(roomMessage.message), {
|
|
411
|
+
createdAt: dateOrNull(roomMessage.message.created_at),
|
|
412
|
+
attachment: roomMessage.attachment,
|
|
413
|
+
});
|
|
351
414
|
};
|
|
352
415
|
this.room = room;
|
|
353
416
|
this.agentName = agentName;
|
|
354
|
-
this.
|
|
417
|
+
this.attachMessagingListeners();
|
|
355
418
|
}
|
|
356
419
|
localParticipantName() {
|
|
357
420
|
const name = this.room.localParticipant?.getAttribute("name");
|
|
@@ -362,12 +425,18 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
362
425
|
return;
|
|
363
426
|
}
|
|
364
427
|
this.started = true;
|
|
428
|
+
this.attachMessagingListeners();
|
|
365
429
|
this.room.messaging.start();
|
|
366
|
-
this.
|
|
430
|
+
this.startRoomStatusListener();
|
|
431
|
+
await this.room.messaging.enable();
|
|
432
|
+
this.waitingForParticipant = true;
|
|
433
|
+
this.onMessagingChanged();
|
|
367
434
|
}
|
|
368
435
|
async stop() {
|
|
369
436
|
this.started = false;
|
|
370
|
-
this.
|
|
437
|
+
this.roomAbortController?.abort();
|
|
438
|
+
this.roomAbortController = undefined;
|
|
439
|
+
this.detachMessagingListeners();
|
|
371
440
|
for (const wait of this.pendingParticipantWaits.values()) {
|
|
372
441
|
if (!wait.completed) {
|
|
373
442
|
wait.completeError(new Error("Chat client stopped while waiting for an agent participant."));
|
|
@@ -375,12 +444,35 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
375
444
|
}
|
|
376
445
|
this.pendingParticipantWaits.clear();
|
|
377
446
|
}
|
|
447
|
+
attachMessagingListeners() {
|
|
448
|
+
if (this.messagingListenersAttached) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
this.room.messaging.addListener("message", this.onMessagingMessage);
|
|
452
|
+
this.room.messaging.addListener("participant_added", this.onMessagingParticipantChanged);
|
|
453
|
+
this.room.messaging.addListener("participant_removed", this.onMessagingParticipantRemoved);
|
|
454
|
+
this.room.messaging.addListener("messaging_enabled", this.onMessagingParticipantChanged);
|
|
455
|
+
this.messagingListenersAttached = true;
|
|
456
|
+
}
|
|
457
|
+
detachMessagingListeners() {
|
|
458
|
+
if (!this.messagingListenersAttached) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
this.room.messaging.removeListener("messaging_enabled", this.onMessagingParticipantChanged);
|
|
462
|
+
this.room.messaging.removeListener("participant_removed", this.onMessagingParticipantRemoved);
|
|
463
|
+
this.room.messaging.removeListener("participant_added", this.onMessagingParticipantChanged);
|
|
464
|
+
this.room.messaging.removeListener("message", this.onMessagingMessage);
|
|
465
|
+
this.messagingListenersAttached = false;
|
|
466
|
+
}
|
|
378
467
|
agentParticipant() {
|
|
379
468
|
const normalizedAgentName = this.agentName?.trim();
|
|
380
469
|
for (const participant of this.room.messaging.remoteParticipants) {
|
|
381
470
|
if (normalizedAgentName != null && normalizedAgentName !== "" && participant.getAttribute("name") !== normalizedAgentName) {
|
|
382
471
|
continue;
|
|
383
472
|
}
|
|
473
|
+
if (normalizedAgentName != null && normalizedAgentName !== "") {
|
|
474
|
+
return participant;
|
|
475
|
+
}
|
|
384
476
|
if (participant.getAttribute("supports_agent_messages") === true) {
|
|
385
477
|
return participant;
|
|
386
478
|
}
|
|
@@ -405,7 +497,13 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
405
497
|
}
|
|
406
498
|
async sendAgentMessage(message, { attachment, ignoreOffline = false } = {}) {
|
|
407
499
|
await this.start();
|
|
408
|
-
|
|
500
|
+
let participant = this.agentParticipant();
|
|
501
|
+
if (participant == null) {
|
|
502
|
+
if (ignoreOffline) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
participant = await this.waitForAgentParticipant({ waitKey: message.messageId });
|
|
506
|
+
}
|
|
409
507
|
await this.room.messaging.sendMessage({
|
|
410
508
|
to: participant,
|
|
411
509
|
type: agent_messages_js_1.agentRoomMessageType,
|
|
@@ -414,8 +512,51 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
414
512
|
ignoreOffline,
|
|
415
513
|
});
|
|
416
514
|
}
|
|
515
|
+
startRoomStatusListener() {
|
|
516
|
+
if (this.roomAbortController != null) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
const controller = new AbortController();
|
|
520
|
+
this.roomAbortController = controller;
|
|
521
|
+
void (async () => {
|
|
522
|
+
for await (const event of this.room.listen({ abortSignal: controller.signal })) {
|
|
523
|
+
if (controller.signal.aborted || event.name !== "room.status") {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
const status = String(event.status ?? "").trim().toLowerCase();
|
|
527
|
+
const message = String(event.message ?? "").trim();
|
|
528
|
+
if (status === "connected" || status === "ready" || status === "reconnected") {
|
|
529
|
+
this.waitingForParticipant = true;
|
|
530
|
+
this.onMessagingChanged();
|
|
531
|
+
}
|
|
532
|
+
else if (status === "disconnected" || status === "reconnecting" || status === "connecting") {
|
|
533
|
+
this.agentParticipantId = undefined;
|
|
534
|
+
this.waitingForParticipant = true;
|
|
535
|
+
this.emitConnectionStatus({
|
|
536
|
+
status: status === "disconnected" ? "disconnected" : "reconnecting",
|
|
537
|
+
message: message !== "" ? message : status === "disconnected" ? "Agent messaging disconnected" : "Waiting for agent messaging",
|
|
538
|
+
reason: message !== "" ? message : undefined,
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
})().catch(() => undefined);
|
|
543
|
+
}
|
|
544
|
+
async reopenOpenSessions() {
|
|
545
|
+
for (const session of this.sessions) {
|
|
546
|
+
if (!session.isOpen) {
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
await session.open({ load: true, sinceTurn: session.lastCompletedTurnId });
|
|
550
|
+
}
|
|
551
|
+
}
|
|
417
552
|
}
|
|
418
553
|
exports.MessagingChatClient = MessagingChatClient;
|
|
554
|
+
function isThreadListMessage(message) {
|
|
555
|
+
return message.type === agent_messages_js_1.agentThreadListedType
|
|
556
|
+
|| message.type === agent_messages_js_1.agentThreadCreatedType
|
|
557
|
+
|| message.type === agent_messages_js_1.agentThreadUpdatedType
|
|
558
|
+
|| message.type === agent_messages_js_1.agentThreadDeletedType;
|
|
559
|
+
}
|
|
419
560
|
class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
420
561
|
constructor({ client, threadPath }) {
|
|
421
562
|
super();
|
|
@@ -463,6 +604,9 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
463
604
|
async open({ load = true, sinceTurn } = {}) {
|
|
464
605
|
if (this.openState) {
|
|
465
606
|
if (load) {
|
|
607
|
+
if (sinceTurn == null) {
|
|
608
|
+
this.resetReplayState();
|
|
609
|
+
}
|
|
466
610
|
const openThread = new agent_messages_js_1.OpenThread({ threadId: this.threadPath, load: true, sinceTurn });
|
|
467
611
|
this.setLoadState(this.loadingStateForOpen(openThread, sinceTurn));
|
|
468
612
|
try {
|
|
@@ -493,6 +637,17 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
493
637
|
throw error;
|
|
494
638
|
}
|
|
495
639
|
}
|
|
640
|
+
resetReplayState() {
|
|
641
|
+
this._messages.length = 0;
|
|
642
|
+
this.messageIndexes.clear();
|
|
643
|
+
this.localAgentMessageIds.clear();
|
|
644
|
+
this.pendingLocalInputMessageIds.clear();
|
|
645
|
+
this.mergedDeltaMessageIds.clear();
|
|
646
|
+
this.pendingInputsById.clear();
|
|
647
|
+
this.lastCompletedTurnIdValue = undefined;
|
|
648
|
+
this.lastAgentMessageType = undefined;
|
|
649
|
+
this.lastAgentMessageAt = undefined;
|
|
650
|
+
}
|
|
496
651
|
async close() {
|
|
497
652
|
if (!this.openState) {
|
|
498
653
|
return;
|
|
@@ -524,7 +679,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
524
679
|
response,
|
|
525
680
|
}));
|
|
526
681
|
}
|
|
527
|
-
async sendText({ messageId, text, attachments, steer = false, turnId, backend, provider, model, voice, outputModalities, senderName, clientToolkits, }) {
|
|
682
|
+
async sendText({ messageId, text, attachments, steer = false, turnId, backend, provider, model, voice, outputModalities, senderName, clientToolkits, toolChoice, }) {
|
|
528
683
|
const resolvedMessageId = messageId == null || messageId.trim() === "" ? (0, uuid_1.v4)() : messageId.trim();
|
|
529
684
|
const currentModel = this.currentModelValue;
|
|
530
685
|
const resolvedBackend = nonEmptyTrimmed(backend) ?? currentModel?.backend;
|
|
@@ -553,6 +708,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
553
708
|
voice: resolvedVoice,
|
|
554
709
|
outputModalities: resolvedOutputModalities,
|
|
555
710
|
clientToolkits: clientToolkits != null && clientToolkits.length > 0 ? clientToolkits : undefined,
|
|
711
|
+
toolChoice: toolChoice?.toJson(),
|
|
556
712
|
});
|
|
557
713
|
this.localAgentMessageIds.add(resolvedMessageId);
|
|
558
714
|
this.pendingLocalInputMessageIds.add(resolvedMessageId);
|
|
@@ -602,9 +758,9 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
602
758
|
const message = event.message;
|
|
603
759
|
const type = message.type;
|
|
604
760
|
this.lastAgentMessageType = type;
|
|
605
|
-
this.lastAgentMessageAt =
|
|
761
|
+
this.lastAgentMessageAt = event.createdAt;
|
|
606
762
|
this.updateSessionState(message);
|
|
607
|
-
this.updatePendingInputsForMessage(message);
|
|
763
|
+
this.updatePendingInputsForMessage(message, event.createdAt);
|
|
608
764
|
this.appendRenderableMessage(event);
|
|
609
765
|
this.notifyListeners();
|
|
610
766
|
}
|
|
@@ -670,7 +826,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
670
826
|
}), { notify: false });
|
|
671
827
|
}
|
|
672
828
|
}
|
|
673
|
-
updatePendingInputsForMessage(message) {
|
|
829
|
+
updatePendingInputsForMessage(message, createdAt) {
|
|
674
830
|
const type = message.type;
|
|
675
831
|
const messageId = message.messageId;
|
|
676
832
|
const sourceMessageId = sourceMessageIdFor(message);
|
|
@@ -684,7 +840,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
684
840
|
messageType: type,
|
|
685
841
|
threadPath: this.threadPath,
|
|
686
842
|
payload: message,
|
|
687
|
-
createdAt
|
|
843
|
+
createdAt,
|
|
688
844
|
awaitingAcceptance: true,
|
|
689
845
|
awaitingApplication: true,
|
|
690
846
|
}));
|
|
@@ -723,6 +879,31 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
723
879
|
}
|
|
724
880
|
return;
|
|
725
881
|
}
|
|
882
|
+
if (message.type === agent_messages_js_1.agentToolCallEndedType) {
|
|
883
|
+
const itemId = message.error == null ? undefined : normalizedString(message.itemId);
|
|
884
|
+
if (itemId != null) {
|
|
885
|
+
this.upsertItemMessage(`tool_call:${itemId}`, event);
|
|
886
|
+
}
|
|
887
|
+
else if (message.error != null) {
|
|
888
|
+
this.appendMessage(event);
|
|
889
|
+
}
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
if (message.type === agent_messages_js_1.agentToolCallPendingType || message.type === agent_messages_js_1.agentToolCallInProgressType || message.type === agent_messages_js_1.agentToolCallStartedType) {
|
|
893
|
+
const itemId = normalizedString(message.itemId);
|
|
894
|
+
if (itemId != null) {
|
|
895
|
+
this.upsertItemMessage(`tool_call:${itemId}`, event);
|
|
896
|
+
}
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
if (message.type === agent_messages_js_1.agentSecretRequestedType) {
|
|
900
|
+
this.appendMessage(event);
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
if (message.type === agent_messages_js_1.agentModelChangedType) {
|
|
904
|
+
this.appendMessage(event);
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
726
907
|
if (message.type === agent_messages_js_1.agentThreadStartType || message.type === agent_messages_js_1.agentTurnStartType || message.type === agent_messages_js_1.agentTurnSteerType) {
|
|
727
908
|
if (agentInputText(message.content).trim() !== "") {
|
|
728
909
|
this.appendMessage(event);
|
|
@@ -738,6 +919,18 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
738
919
|
if (agentInputText(message.content).trim() !== "") {
|
|
739
920
|
this.appendMessage(event, { beforePendingLocalInputs: true });
|
|
740
921
|
}
|
|
922
|
+
else {
|
|
923
|
+
this.appendMessage(event);
|
|
924
|
+
}
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
if (message.type === agent_messages_js_1.agentTurnStartedType ||
|
|
928
|
+
message.type === agent_messages_js_1.agentTurnSteeredType ||
|
|
929
|
+
message.type === agent_messages_js_1.agentTurnStartRejectedType ||
|
|
930
|
+
message.type === agent_messages_js_1.agentTurnSteerRejectedType ||
|
|
931
|
+
message.type === agent_messages_js_1.agentTurnInterruptAcceptedType ||
|
|
932
|
+
message.type === agent_messages_js_1.agentTurnInterruptedType) {
|
|
933
|
+
this.appendMessage(event);
|
|
741
934
|
return;
|
|
742
935
|
}
|
|
743
936
|
if (isMergeableDelta(message)) {
|
|
@@ -751,6 +944,10 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
751
944
|
}
|
|
752
945
|
return;
|
|
753
946
|
}
|
|
947
|
+
if (message.type === agent_messages_js_1.agentUsageUpdatedType) {
|
|
948
|
+
this.appendMessage(event);
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
754
951
|
if (message instanceof agent_messages_js_1.AgentClientToolCallRequested) {
|
|
755
952
|
this.appendMessage(event);
|
|
756
953
|
}
|
|
@@ -803,7 +1000,7 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
803
1000
|
const existing = this._messages[existingIndex].message;
|
|
804
1001
|
const merged = mergeDeltaMessage(existing, message);
|
|
805
1002
|
if (merged != null) {
|
|
806
|
-
this._messages[existingIndex] = new AgentMessageEvent({ message: merged, attachment: event.attachment });
|
|
1003
|
+
this._messages[existingIndex] = new AgentMessageEvent({ message: merged, createdAt: event.createdAt, attachment: event.attachment });
|
|
807
1004
|
}
|
|
808
1005
|
}
|
|
809
1006
|
indexMessagesFrom(start) {
|
|
@@ -968,6 +1165,16 @@ function normalizedString(value) {
|
|
|
968
1165
|
const normalized = value?.trim();
|
|
969
1166
|
return normalized == null || normalized === "" ? undefined : normalized;
|
|
970
1167
|
}
|
|
1168
|
+
function dateOrNull(value) {
|
|
1169
|
+
if (value instanceof Date && !Number.isNaN(value.getTime())) {
|
|
1170
|
+
return value;
|
|
1171
|
+
}
|
|
1172
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
1173
|
+
return undefined;
|
|
1174
|
+
}
|
|
1175
|
+
const parsed = new Date(value);
|
|
1176
|
+
return Number.isNaN(parsed.getTime()) ? undefined : parsed;
|
|
1177
|
+
}
|
|
971
1178
|
function nonEmptyTrimmed(value) {
|
|
972
1179
|
const normalized = value?.trim();
|
|
973
1180
|
return normalized == null || normalized === "" ? undefined : normalized;
|
|
@@ -93,6 +93,7 @@ export declare class AgentThreadStorageRepository extends ThreadStorageRepositor
|
|
|
93
93
|
renameThread(threadPath: string, name: string): Promise<void>;
|
|
94
94
|
private requestList;
|
|
95
95
|
private handleEvent;
|
|
96
|
+
private reconnectWatch;
|
|
96
97
|
private handleThreadsListed;
|
|
97
98
|
private upsertThread;
|
|
98
99
|
private entryFromAgentThread;
|
|
@@ -313,10 +313,12 @@ class AgentThreadStorageRepository extends ThreadStorageRepository {
|
|
|
313
313
|
this.handleEvent(next.value);
|
|
314
314
|
}
|
|
315
315
|
})();
|
|
316
|
-
|
|
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()];
|
|
@@ -364,6 +367,12 @@ class AgentThreadStorageRepository extends ThreadStorageRepository {
|
|
|
364
367
|
}
|
|
365
368
|
handleEvent(event) {
|
|
366
369
|
const message = event.message;
|
|
370
|
+
if (message.type === "meshagent.agent.connection.status") {
|
|
371
|
+
if (String(message.status ?? "").trim().toLowerCase() === "reconnected") {
|
|
372
|
+
void this.reconnectWatch();
|
|
373
|
+
}
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
367
376
|
if (message.type === "meshagent.agent.thread.listed") {
|
|
368
377
|
this.handleThreadsListed(message);
|
|
369
378
|
return;
|
|
@@ -383,6 +392,13 @@ class AgentThreadStorageRepository extends ThreadStorageRepository {
|
|
|
383
392
|
}
|
|
384
393
|
}
|
|
385
394
|
}
|
|
395
|
+
async reconnectWatch() {
|
|
396
|
+
if (this.closed) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
await this.chatClient.sendAgentMessage(new agent_messages_js_1.WatchThreads(), { ignoreOffline: true });
|
|
400
|
+
await this.requestList();
|
|
401
|
+
}
|
|
386
402
|
handleThreadsListed(message) {
|
|
387
403
|
const nextEntries = new Map();
|
|
388
404
|
for (const thread of message.threads) {
|
|
@@ -19,6 +19,8 @@ export declare const agentParticipantDisconnectType = "meshagent.agent.participa
|
|
|
19
19
|
export declare const agentThreadDeleteType = "meshagent.agent.thread.delete";
|
|
20
20
|
export declare const agentThreadRenameType = "meshagent.agent.thread.rename";
|
|
21
21
|
export declare const agentThreadListType = "meshagent.agent.thread.list";
|
|
22
|
+
export declare const agentThreadWatchType = "meshagent.agent.thread.watch";
|
|
23
|
+
export declare const agentThreadUnwatchType = "meshagent.agent.thread.unwatch";
|
|
22
24
|
export declare const agentThreadListedType = "meshagent.agent.thread.listed";
|
|
23
25
|
export declare const agentThreadCreatedType = "meshagent.agent.thread.created";
|
|
24
26
|
export declare const agentThreadUpdatedType = "meshagent.agent.thread.updated";
|
|
@@ -239,7 +241,8 @@ export declare abstract class AgentMessage {
|
|
|
239
241
|
readonly type: string;
|
|
240
242
|
readonly messageId: string;
|
|
241
243
|
readonly senderName?: string;
|
|
242
|
-
|
|
244
|
+
readonly createdAt: string;
|
|
245
|
+
protected constructor({ type, messageId, message_id, senderName, sender_name, createdAt, created_at }: JsonMap);
|
|
243
246
|
toJson(): JsonMap;
|
|
244
247
|
static fromJson(json: JsonMap): AgentMessage;
|
|
245
248
|
}
|
|
@@ -272,6 +275,8 @@ export declare const ParticipantDisconnect: MessageCtor;
|
|
|
272
275
|
export declare const DeleteThread: MessageCtor;
|
|
273
276
|
export declare const RenameThread: MessageCtor;
|
|
274
277
|
export declare const ListThreads: MessageCtor;
|
|
278
|
+
export declare const WatchThreads: MessageCtor;
|
|
279
|
+
export declare const UnwatchThreads: MessageCtor;
|
|
275
280
|
export declare const ThreadsListed: MessageCtor;
|
|
276
281
|
export declare const ThreadCreated: MessageCtor;
|
|
277
282
|
export declare const ThreadUpdated: MessageCtor;
|
|
@@ -18,6 +18,8 @@ export const agentParticipantDisconnectType = "meshagent.agent.participant.disco
|
|
|
18
18
|
export const agentThreadDeleteType = "meshagent.agent.thread.delete";
|
|
19
19
|
export const agentThreadRenameType = "meshagent.agent.thread.rename";
|
|
20
20
|
export const agentThreadListType = "meshagent.agent.thread.list";
|
|
21
|
+
export const agentThreadWatchType = "meshagent.agent.thread.watch";
|
|
22
|
+
export const agentThreadUnwatchType = "meshagent.agent.thread.unwatch";
|
|
21
23
|
export const agentThreadListedType = "meshagent.agent.thread.listed";
|
|
22
24
|
export const agentThreadCreatedType = "meshagent.agent.thread.created";
|
|
23
25
|
export const agentThreadUpdatedType = "meshagent.agent.thread.updated";
|
|
@@ -631,16 +633,18 @@ function omitUndefined(value) {
|
|
|
631
633
|
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
632
634
|
}
|
|
633
635
|
export class AgentMessage {
|
|
634
|
-
constructor({ type, messageId, message_id, senderName, sender_name }) {
|
|
636
|
+
constructor({ type, messageId, message_id, senderName, sender_name, createdAt, created_at }) {
|
|
635
637
|
this.type = String(type);
|
|
636
638
|
const resolvedMessageId = stringOrNull(messageId ?? message_id)?.trim();
|
|
637
639
|
this.messageId = resolvedMessageId == null || resolvedMessageId.length === 0 ? uuidv4() : resolvedMessageId;
|
|
638
640
|
this.senderName = stringOrNull(senderName ?? sender_name);
|
|
641
|
+
this.createdAt = stringOrNull(createdAt ?? created_at) ?? new Date().toISOString();
|
|
639
642
|
}
|
|
640
643
|
toJson() {
|
|
641
644
|
return {
|
|
642
645
|
type: this.type,
|
|
643
646
|
message_id: this.messageId,
|
|
647
|
+
created_at: this.createdAt,
|
|
644
648
|
...(this.senderName != null ? { sender_name: this.senderName } : {}),
|
|
645
649
|
};
|
|
646
650
|
}
|
|
@@ -704,6 +708,7 @@ function makeMessageClass({ type, base = "message", fields = [], }) {
|
|
|
704
708
|
const params = {
|
|
705
709
|
messageId: stringOrNull(json.message_id),
|
|
706
710
|
senderName: stringOrNull(json.sender_name),
|
|
711
|
+
createdAt: stringOrNull(json.created_at),
|
|
707
712
|
};
|
|
708
713
|
if (base !== "message") {
|
|
709
714
|
params.threadId = requiredString(json, "thread_id");
|
|
@@ -914,6 +919,8 @@ export const ParticipantDisconnect = makeMessageClass({ type: agentParticipantDi
|
|
|
914
919
|
export const DeleteThread = makeMessageClass({ type: agentThreadDeleteType, base: "thread" });
|
|
915
920
|
export const RenameThread = makeMessageClass({ type: agentThreadRenameType, base: "thread", fields: [s("name", "name", true)] });
|
|
916
921
|
export const ListThreads = makeMessageClass({ type: agentThreadListType, fields: [{ prop: "limit", json: "limit", from: (value) => intOrNull(value) ?? 200, default: () => 200, always: true }, { prop: "offset", json: "offset", from: (value) => intOrNull(value) ?? 0, default: () => 0, always: true }] });
|
|
922
|
+
export const WatchThreads = makeMessageClass({ type: agentThreadWatchType });
|
|
923
|
+
export const UnwatchThreads = makeMessageClass({ type: agentThreadUnwatchType });
|
|
917
924
|
export const ThreadsListed = makeMessageClass({ type: agentThreadListedType, fields: [s("sourceMessageId", "source_message_id", true), objList("threads", "threads", AgentThreadListEntry.fromJson, true), i("total"), i("offset"), i("limit")] });
|
|
918
925
|
export const ThreadCreated = makeMessageClass({ type: agentThreadCreatedType, fields: [obj("thread", "thread", AgentThreadListEntry.fromJson, true)] });
|
|
919
926
|
export const ThreadUpdated = makeMessageClass({ type: agentThreadUpdatedType, fields: [obj("thread", "thread", AgentThreadListEntry.fromJson, true)] });
|