@meshagent/meshagent-agents 0.43.2 → 0.43.3
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 +3 -0
- package/dist/browser/agent-messages.d.ts +1 -0
- package/dist/browser/agent-messages.js +11 -6
- package/dist/browser/chat-client.d.ts +33 -9
- package/dist/browser/chat-client.js +416 -84
- package/dist/esm/agent-messages.d.ts +1 -0
- package/dist/esm/agent-messages.js +11 -6
- package/dist/esm/chat-client.d.ts +33 -9
- package/dist/esm/chat-client.js +418 -86
- package/dist/node/agent-messages.d.ts +1 -0
- package/dist/node/agent-messages.js +11 -6
- package/dist/node/chat-client.d.ts +33 -9
- package/dist/node/chat-client.js +416 -84
- package/package.json +2 -2
|
@@ -15,6 +15,30 @@ class AgentMessageEvent {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
exports.AgentMessageEvent = AgentMessageEvent;
|
|
18
|
+
function agentRoomMessageFromEvent(event) {
|
|
19
|
+
const candidate = event.message;
|
|
20
|
+
if (candidate == null || typeof candidate !== "object" || Array.isArray(candidate)) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
const roomMessage = candidate;
|
|
24
|
+
if (roomMessage.type !== agent_messages_js_1.agentRoomMessageType) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
if (roomMessage.message == null || typeof roomMessage.message !== "object" || Array.isArray(roomMessage.message)) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const rawMessage = roomMessage.message;
|
|
31
|
+
const payload = typeof rawMessage.type === "string" ? rawMessage : rawMessage.payload;
|
|
32
|
+
if (payload == null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
fromParticipantId: typeof roomMessage.fromParticipantId === "string" ? roomMessage.fromParticipantId : undefined,
|
|
37
|
+
message: payload,
|
|
38
|
+
local: roomMessage.local === true,
|
|
39
|
+
attachment: roomMessage.attachment instanceof Uint8Array ? roomMessage.attachment : undefined,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
18
42
|
class PendingAgentInput {
|
|
19
43
|
constructor({ messageId, messageType, threadPath, payload, createdAt, awaitingAcceptance = false, awaitingApplication = false, awaitingOnline = false, }) {
|
|
20
44
|
this.messageId = messageId;
|
|
@@ -76,28 +100,52 @@ class ChatThreadStartResult {
|
|
|
76
100
|
exports.ChatThreadStartResult = ChatThreadStartResult;
|
|
77
101
|
class EventQueue {
|
|
78
102
|
constructor() {
|
|
79
|
-
this.
|
|
80
|
-
this.waiters = [];
|
|
103
|
+
this.subscribers = new Set();
|
|
81
104
|
}
|
|
82
105
|
add(item) {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
106
|
+
for (const subscriber of this.subscribers) {
|
|
107
|
+
if (subscriber.closed) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const waiter = subscriber.waiters.shift();
|
|
111
|
+
if (waiter != null) {
|
|
112
|
+
waiter({ value: item, done: false });
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
subscriber.items.push(item);
|
|
116
|
+
}
|
|
87
117
|
}
|
|
88
|
-
this.items.push(item);
|
|
89
118
|
}
|
|
90
119
|
get stream() {
|
|
91
120
|
return {
|
|
92
|
-
[Symbol.asyncIterator]: () =>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
121
|
+
[Symbol.asyncIterator]: () => {
|
|
122
|
+
const subscriber = {
|
|
123
|
+
items: [],
|
|
124
|
+
waiters: [],
|
|
125
|
+
closed: false,
|
|
126
|
+
};
|
|
127
|
+
this.subscribers.add(subscriber);
|
|
128
|
+
return {
|
|
129
|
+
next: async () => {
|
|
130
|
+
if (subscriber.closed) {
|
|
131
|
+
return { done: true, value: undefined };
|
|
132
|
+
}
|
|
133
|
+
const item = subscriber.items.shift();
|
|
134
|
+
if (item !== undefined) {
|
|
135
|
+
return { value: item, done: false };
|
|
136
|
+
}
|
|
137
|
+
return new Promise((resolve) => subscriber.waiters.push(resolve));
|
|
138
|
+
},
|
|
139
|
+
return: async () => {
|
|
140
|
+
subscriber.closed = true;
|
|
141
|
+
this.subscribers.delete(subscriber);
|
|
142
|
+
for (const waiter of subscriber.waiters.splice(0)) {
|
|
143
|
+
waiter({ done: true, value: undefined });
|
|
144
|
+
}
|
|
145
|
+
return { done: true, value: undefined };
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
},
|
|
101
149
|
};
|
|
102
150
|
}
|
|
103
151
|
}
|
|
@@ -106,6 +154,7 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
106
154
|
super(...arguments);
|
|
107
155
|
this.sessionsByPath = new Map();
|
|
108
156
|
this.pendingStartRequests = new Map();
|
|
157
|
+
this.pendingSessionEventsByPath = new Map();
|
|
109
158
|
this.eventQueue = new EventQueue();
|
|
110
159
|
}
|
|
111
160
|
get events() {
|
|
@@ -128,7 +177,7 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
128
177
|
cleanParticipantName(value) {
|
|
129
178
|
return nonEmptyTrimmed(value);
|
|
130
179
|
}
|
|
131
|
-
openThread(threadPath, { load = true, sinceTurn, reloadIfOpen = false } = {}) {
|
|
180
|
+
openThread(threadPath, { load = true, sinceTurn, reloadIfOpen = false, drainPendingEvents = true, } = {}) {
|
|
132
181
|
const normalized = threadPath.trim();
|
|
133
182
|
if (normalized === "") {
|
|
134
183
|
throw new TypeError("thread path cannot be empty");
|
|
@@ -136,23 +185,32 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
136
185
|
const existing = this.sessionsByPath.get(normalized);
|
|
137
186
|
if (existing != null) {
|
|
138
187
|
if (!existing.isOpen || reloadIfOpen) {
|
|
139
|
-
|
|
188
|
+
this.openSession(existing, { load, sinceTurn });
|
|
140
189
|
}
|
|
141
190
|
return existing;
|
|
142
191
|
}
|
|
143
192
|
const created = new ChatThreadSession({ client: this, threadPath: normalized });
|
|
144
193
|
this.sessionsByPath.set(normalized, created);
|
|
145
|
-
|
|
194
|
+
if (drainPendingEvents) {
|
|
195
|
+
this.drainPendingSessionEvents(normalized, created);
|
|
196
|
+
}
|
|
197
|
+
this.openSession(created, { load, sinceTurn });
|
|
146
198
|
this.notifyListeners();
|
|
147
199
|
return created;
|
|
148
200
|
}
|
|
149
|
-
|
|
201
|
+
openSession(session, options) {
|
|
202
|
+
void session.open(options).catch(() => {
|
|
203
|
+
this.notifyListeners();
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
async startThread({ messageId, message, attachments, name, backend, provider, model, voice, outputModalities, realtimeProtocol, senderName, clientToolkits, omitContent = false, }) {
|
|
150
207
|
const resolvedMessageId = messageId == null || messageId.trim() === "" ? (0, uuid_1.v4)() : messageId.trim();
|
|
151
208
|
const resolvedSenderName = this.cleanParticipantName(senderName) ?? this.localParticipantName();
|
|
152
209
|
const payload = new agent_messages_js_1.StartThread({
|
|
153
210
|
messageId: resolvedMessageId,
|
|
154
211
|
content: omitContent ? undefined : (0, agent_messages_js_1.agentInputContent)({ text: message, attachments }),
|
|
155
212
|
name: nonEmptyTrimmed(name),
|
|
213
|
+
backend: nonEmptyTrimmed(backend),
|
|
156
214
|
provider: nonEmptyTrimmed(provider),
|
|
157
215
|
model: nonEmptyTrimmed(model),
|
|
158
216
|
voice: nonEmptyTrimmed(voice),
|
|
@@ -172,10 +230,11 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
172
230
|
if (threadPath === "") {
|
|
173
231
|
throw new Error("Agent did not return a thread_id for the new thread.");
|
|
174
232
|
}
|
|
175
|
-
const session = this.openThread(threadPath, { load: false });
|
|
233
|
+
const session = this.openThread(threadPath, { load: false, drainPendingEvents: false });
|
|
176
234
|
if (!omitContent) {
|
|
177
235
|
session.addAgentMessage(new AgentMessageEvent({ message: payload }));
|
|
178
236
|
}
|
|
237
|
+
this.drainPendingSessionEvents(threadPath, session);
|
|
179
238
|
return new ChatThreadStartResult({
|
|
180
239
|
session,
|
|
181
240
|
threadPath,
|
|
@@ -188,6 +247,16 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
188
247
|
this.pendingStartRequests.delete(resolvedMessageId);
|
|
189
248
|
}
|
|
190
249
|
}
|
|
250
|
+
drainPendingSessionEvents(threadPath, session) {
|
|
251
|
+
const pendingEvents = this.pendingSessionEventsByPath.get(threadPath);
|
|
252
|
+
if (pendingEvents == null) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
this.pendingSessionEventsByPath.delete(threadPath);
|
|
256
|
+
for (const event of pendingEvents) {
|
|
257
|
+
session.addAgentMessage(event);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
191
260
|
handleAgentMessage(message, { attachment } = {}) {
|
|
192
261
|
if (message.type === agent_messages_js_1.agentConnectionStatusType) {
|
|
193
262
|
this._connectionStatus = message;
|
|
@@ -212,7 +281,16 @@ class BaseChatClient extends change_emitter_js_1.ChangeEmitter {
|
|
|
212
281
|
this.notifyListeners();
|
|
213
282
|
return;
|
|
214
283
|
}
|
|
215
|
-
|
|
284
|
+
const event = new AgentMessageEvent({ message, attachment });
|
|
285
|
+
const session = this.sessionsByPath.get(threadPath);
|
|
286
|
+
if (session != null) {
|
|
287
|
+
session.addAgentMessage(event);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
const pending = this.pendingSessionEventsByPath.get(threadPath) ?? [];
|
|
291
|
+
pending.push(event);
|
|
292
|
+
this.pendingSessionEventsByPath.set(threadPath, pending);
|
|
293
|
+
}
|
|
216
294
|
this.notifyListeners();
|
|
217
295
|
}
|
|
218
296
|
emitConnectionStatus({ status, message, reason, retryDelay, }) {
|
|
@@ -246,7 +324,6 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
246
324
|
constructor({ room, agentName }) {
|
|
247
325
|
super();
|
|
248
326
|
this.pendingParticipantWaits = new Map();
|
|
249
|
-
this.roomAbortController = new AbortController();
|
|
250
327
|
this.started = false;
|
|
251
328
|
this.onMessagingChanged = () => {
|
|
252
329
|
const participant = this.agentParticipant();
|
|
@@ -260,10 +337,21 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
260
337
|
}
|
|
261
338
|
this.notifyListeners();
|
|
262
339
|
};
|
|
340
|
+
this.onMessagingMessage = (event) => {
|
|
341
|
+
this.onMessagingChanged();
|
|
342
|
+
const roomMessage = agentRoomMessageFromEvent(event);
|
|
343
|
+
if (roomMessage == null || roomMessage.local) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const participant = this.agentParticipant();
|
|
347
|
+
if (participant == null || roomMessage.fromParticipantId !== participant.id) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
this.handleAgentMessage(agent_messages_js_1.AgentMessage.fromJson(roomMessage.message), { attachment: roomMessage.attachment });
|
|
351
|
+
};
|
|
263
352
|
this.room = room;
|
|
264
353
|
this.agentName = agentName;
|
|
265
|
-
this.room.messaging.addListener("message", this.
|
|
266
|
-
this.roomPump = this.consumeRoomEvents();
|
|
354
|
+
this.room.messaging.addListener("message", this.onMessagingMessage);
|
|
267
355
|
}
|
|
268
356
|
localParticipantName() {
|
|
269
357
|
const name = this.room.localParticipant?.getAttribute("name");
|
|
@@ -279,15 +367,13 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
279
367
|
}
|
|
280
368
|
async stop() {
|
|
281
369
|
this.started = false;
|
|
282
|
-
this.
|
|
283
|
-
this.room.messaging.removeListener("message", this.onMessagingChanged);
|
|
370
|
+
this.room.messaging.removeListener("message", this.onMessagingMessage);
|
|
284
371
|
for (const wait of this.pendingParticipantWaits.values()) {
|
|
285
372
|
if (!wait.completed) {
|
|
286
373
|
wait.completeError(new Error("Chat client stopped while waiting for an agent participant."));
|
|
287
374
|
}
|
|
288
375
|
}
|
|
289
376
|
this.pendingParticipantWaits.clear();
|
|
290
|
-
await this.roomPump?.catch(() => undefined);
|
|
291
377
|
}
|
|
292
378
|
agentParticipant() {
|
|
293
379
|
const normalizedAgentName = this.agentName?.trim();
|
|
@@ -328,38 +414,16 @@ class MessagingChatClient extends BaseChatClient {
|
|
|
328
414
|
ignoreOffline,
|
|
329
415
|
});
|
|
330
416
|
}
|
|
331
|
-
async consumeRoomEvents() {
|
|
332
|
-
try {
|
|
333
|
-
for await (const event of this.room.listen({ abortSignal: this.roomAbortController.signal })) {
|
|
334
|
-
this.onRoomEvent(event);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
catch {
|
|
338
|
-
if (!this.roomAbortController.signal.aborted) {
|
|
339
|
-
throw new Error("chat client room event listener stopped unexpectedly");
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
onRoomEvent(event) {
|
|
344
|
-
if (!(event instanceof meshagent_1.RoomMessageEvent) || event.message.type !== agent_messages_js_1.agentRoomMessageType) {
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
const participant = this.agentParticipant();
|
|
348
|
-
if (participant == null || event.message.fromParticipantId !== participant.id) {
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
const message = event.message.message;
|
|
352
|
-
const rawPayload = typeof message.type === "string" ? message : message.payload;
|
|
353
|
-
if (rawPayload != null && typeof rawPayload === "object" && !Array.isArray(rawPayload)) {
|
|
354
|
-
this.handleAgentMessage(agent_messages_js_1.AgentMessage.fromJson(rawPayload), { attachment: event.message.attachment });
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
417
|
}
|
|
358
418
|
exports.MessagingChatClient = MessagingChatClient;
|
|
359
419
|
class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
360
420
|
constructor({ client, threadPath }) {
|
|
361
421
|
super();
|
|
362
422
|
this._messages = [];
|
|
423
|
+
this.messageIndexes = new Map();
|
|
424
|
+
this.localAgentMessageIds = new Set();
|
|
425
|
+
this.pendingLocalInputMessageIds = new Set();
|
|
426
|
+
this.mergedDeltaMessageIds = new Set();
|
|
363
427
|
this.pendingInputsById = new Map();
|
|
364
428
|
this.openState = false;
|
|
365
429
|
this.loadStateValue = ChatThreadSessionLoadState.idle();
|
|
@@ -384,6 +448,18 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
384
448
|
get lastCompletedTurnId() {
|
|
385
449
|
return this.lastCompletedTurnIdValue;
|
|
386
450
|
}
|
|
451
|
+
get activeTurnId() {
|
|
452
|
+
return this.activeTurnIdValue;
|
|
453
|
+
}
|
|
454
|
+
get threadStatus() {
|
|
455
|
+
return this.threadStatusValue;
|
|
456
|
+
}
|
|
457
|
+
get currentModel() {
|
|
458
|
+
return this.currentModelValue;
|
|
459
|
+
}
|
|
460
|
+
get modelsResponse() {
|
|
461
|
+
return this.modelsResponseValue;
|
|
462
|
+
}
|
|
387
463
|
async open({ load = true, sinceTurn } = {}) {
|
|
388
464
|
if (this.openState) {
|
|
389
465
|
if (load) {
|
|
@@ -427,10 +503,11 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
427
503
|
requestModels({ ignoreOffline = false } = {}) {
|
|
428
504
|
return this.client.sendAgentMessage(new agent_messages_js_1.ModelsRequest({ messageId: (0, uuid_1.v4)() }), { ignoreOffline });
|
|
429
505
|
}
|
|
430
|
-
changeModel({ provider, model, voice }) {
|
|
506
|
+
changeModel({ backend, provider, model, voice }) {
|
|
431
507
|
return this.client.sendAgentMessage(new agent_messages_js_1.ChangeModel({
|
|
432
508
|
threadId: this.threadPath,
|
|
433
509
|
messageId: (0, uuid_1.v4)(),
|
|
510
|
+
backend: nonEmptyTrimmed(backend),
|
|
434
511
|
provider,
|
|
435
512
|
model,
|
|
436
513
|
voice: nonEmptyTrimmed(voice),
|
|
@@ -447,8 +524,16 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
447
524
|
response,
|
|
448
525
|
}));
|
|
449
526
|
}
|
|
450
|
-
async sendText({ messageId, text, attachments, steer = false, turnId, provider, model, voice, outputModalities, senderName, clientToolkits, }) {
|
|
527
|
+
async sendText({ messageId, text, attachments, steer = false, turnId, backend, provider, model, voice, outputModalities, senderName, clientToolkits, }) {
|
|
451
528
|
const resolvedMessageId = messageId == null || messageId.trim() === "" ? (0, uuid_1.v4)() : messageId.trim();
|
|
529
|
+
const currentModel = this.currentModelValue;
|
|
530
|
+
const resolvedBackend = nonEmptyTrimmed(backend) ?? currentModel?.backend;
|
|
531
|
+
const resolvedProvider = nonEmptyTrimmed(provider) ?? currentModel?.provider;
|
|
532
|
+
const resolvedModel = nonEmptyTrimmed(model) ?? currentModel?.model;
|
|
533
|
+
const resolvedVoice = nonEmptyTrimmed(voice) ?? currentModel?.voice;
|
|
534
|
+
const resolvedOutputModalities = outputModalities != null && outputModalities.length > 0
|
|
535
|
+
? outputModalities
|
|
536
|
+
: currentModel?.outputModalities;
|
|
452
537
|
const payload = steer
|
|
453
538
|
? new agent_messages_js_1.TurnSteer({
|
|
454
539
|
threadId: this.threadPath,
|
|
@@ -462,21 +547,15 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
462
547
|
messageId: resolvedMessageId,
|
|
463
548
|
senderName: nonEmptyTrimmed(senderName),
|
|
464
549
|
content: (0, agent_messages_js_1.agentInputContent)({ text, attachments }),
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
550
|
+
backend: resolvedBackend,
|
|
551
|
+
provider: resolvedProvider,
|
|
552
|
+
model: resolvedModel,
|
|
553
|
+
voice: resolvedVoice,
|
|
554
|
+
outputModalities: resolvedOutputModalities,
|
|
469
555
|
clientToolkits: clientToolkits != null && clientToolkits.length > 0 ? clientToolkits : undefined,
|
|
470
556
|
});
|
|
471
|
-
this.
|
|
472
|
-
|
|
473
|
-
messageType: payload.type,
|
|
474
|
-
threadPath: this.threadPath,
|
|
475
|
-
payload,
|
|
476
|
-
createdAt: new Date(),
|
|
477
|
-
awaitingAcceptance: true,
|
|
478
|
-
awaitingApplication: true,
|
|
479
|
-
}));
|
|
557
|
+
this.localAgentMessageIds.add(resolvedMessageId);
|
|
558
|
+
this.pendingLocalInputMessageIds.add(resolvedMessageId);
|
|
480
559
|
this.addAgentMessage(new AgentMessageEvent({ message: payload }));
|
|
481
560
|
try {
|
|
482
561
|
await this.client.sendAgentMessage(payload);
|
|
@@ -520,16 +599,86 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
520
599
|
return this.client.sendAgentMessage(new agent_messages_js_1.RenameThread({ threadId: threadPath, name }));
|
|
521
600
|
}
|
|
522
601
|
addAgentMessage(event) {
|
|
523
|
-
this._messages.push(event);
|
|
524
602
|
const message = event.message;
|
|
525
603
|
const type = message.type;
|
|
526
604
|
this.lastAgentMessageType = type;
|
|
527
605
|
this.lastAgentMessageAt = new Date();
|
|
606
|
+
this.updateSessionState(message);
|
|
607
|
+
this.updatePendingInputsForMessage(message);
|
|
608
|
+
this.appendRenderableMessage(event);
|
|
609
|
+
this.notifyListeners();
|
|
610
|
+
}
|
|
611
|
+
updateSessionState(message) {
|
|
612
|
+
if (message.type === agent_messages_js_1.agentTurnEndedType) {
|
|
613
|
+
const turnId = normalizedString(threadMessageValue(message, "turnId"));
|
|
614
|
+
if (turnId != null) {
|
|
615
|
+
this.lastCompletedTurnIdValue = turnId;
|
|
616
|
+
if (this.activeTurnIdValue === turnId) {
|
|
617
|
+
this.activeTurnIdValue = undefined;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
const statusTurnId = normalizedString(this.threadStatusValue?.turnId);
|
|
621
|
+
if (statusTurnId == null || statusTurnId === turnId) {
|
|
622
|
+
this.threadStatusValue = undefined;
|
|
623
|
+
}
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
if (message.type === agent_messages_js_1.agentTurnStartAcceptedType || message.type === agent_messages_js_1.agentTurnStartedType) {
|
|
627
|
+
const turnId = normalizedString(threadMessageValue(message, "turnId"));
|
|
628
|
+
if (turnId != null) {
|
|
629
|
+
this.activeTurnIdValue = turnId;
|
|
630
|
+
}
|
|
631
|
+
if (message.type === agent_messages_js_1.agentTurnStartedType) {
|
|
632
|
+
const statusTurnId = normalizedString(this.threadStatusValue?.turnId);
|
|
633
|
+
if (statusTurnId == null || statusTurnId === turnId) {
|
|
634
|
+
this.threadStatusValue = undefined;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
if (message.type === agent_messages_js_1.agentThreadStatusType && message instanceof agent_messages_js_1.AgentThreadStatus) {
|
|
640
|
+
this.threadStatusValue = message;
|
|
641
|
+
const mode = normalizedString(message.mode);
|
|
642
|
+
const status = normalizedString(message.status);
|
|
643
|
+
const turnId = normalizedString(message.turnId);
|
|
644
|
+
if (status != null && mode === "steerable" && turnId != null) {
|
|
645
|
+
this.activeTurnIdValue = turnId;
|
|
646
|
+
}
|
|
647
|
+
else if (status == null && turnId != null && this.activeTurnIdValue === turnId) {
|
|
648
|
+
this.activeTurnIdValue = undefined;
|
|
649
|
+
}
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
if (message.type === agent_messages_js_1.agentModelChangedType && message instanceof agent_messages_js_1.AgentModelChanged) {
|
|
653
|
+
this.currentModelValue = message;
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
if (message.type === agent_messages_js_1.agentModelsResponseType && message instanceof agent_messages_js_1.ModelsResponse) {
|
|
657
|
+
this.modelsResponseValue = message;
|
|
658
|
+
this.applyActiveModel(message);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
if (message.type === agent_messages_js_1.agentThreadLoadedType) {
|
|
662
|
+
this.setLoadState(new ChatThreadSessionLoadState({
|
|
663
|
+
phase: ChatThreadSessionLoadPhase.Loaded,
|
|
664
|
+
startedAt: this.loadStateValue.startedAt,
|
|
665
|
+
completedAt: this.lastAgentMessageAt,
|
|
666
|
+
requestMessageId: this.loadStateValue.requestMessageId,
|
|
667
|
+
sinceTurn: this.loadStateValue.sinceTurn,
|
|
668
|
+
lastMessageType: message.type,
|
|
669
|
+
lastMessageAt: this.lastAgentMessageAt,
|
|
670
|
+
}), { notify: false });
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
updatePendingInputsForMessage(message) {
|
|
674
|
+
const type = message.type;
|
|
528
675
|
const messageId = message.messageId;
|
|
529
676
|
const sourceMessageId = sourceMessageIdFor(message);
|
|
530
|
-
if (type === agent_messages_js_1.agentTurnStartType || type === agent_messages_js_1.agentTurnSteerType) {
|
|
677
|
+
if (type === agent_messages_js_1.agentThreadStartType || type === agent_messages_js_1.agentTurnStartType || type === agent_messages_js_1.agentTurnSteerType) {
|
|
531
678
|
const normalizedMessageId = messageId.trim();
|
|
532
679
|
if (normalizedMessageId !== "") {
|
|
680
|
+
this.localAgentMessageIds.add(normalizedMessageId);
|
|
681
|
+
this.pendingLocalInputMessageIds.add(normalizedMessageId);
|
|
533
682
|
this.markPending(new PendingAgentInput({
|
|
534
683
|
messageId: normalizedMessageId,
|
|
535
684
|
messageType: type,
|
|
@@ -541,37 +690,152 @@ class ChatThreadSession extends change_emitter_js_1.ChangeEmitter {
|
|
|
541
690
|
}));
|
|
542
691
|
}
|
|
543
692
|
}
|
|
693
|
+
else if (type === agent_messages_js_1.agentThreadStartRejectedType) {
|
|
694
|
+
if (sourceMessageId != null) {
|
|
695
|
+
this.pendingInputsById.delete(sourceMessageId);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
544
698
|
else if (type === agent_messages_js_1.agentTurnStartAcceptedType || type === agent_messages_js_1.agentTurnSteerAcceptedType) {
|
|
545
699
|
this.updatePending(sourceMessageId, { awaitingAcceptance: false, awaitingApplication: true });
|
|
546
700
|
}
|
|
547
701
|
else if (type === agent_messages_js_1.agentTurnStartedType || type === agent_messages_js_1.agentTurnSteeredType) {
|
|
548
702
|
if (sourceMessageId != null) {
|
|
549
703
|
this.pendingInputsById.delete(sourceMessageId);
|
|
704
|
+
this.pendingLocalInputMessageIds.delete(sourceMessageId);
|
|
550
705
|
}
|
|
551
706
|
}
|
|
552
707
|
else if (type === agent_messages_js_1.agentTurnStartRejectedType || type === agent_messages_js_1.agentTurnSteerRejectedType) {
|
|
553
708
|
if (sourceMessageId != null) {
|
|
554
709
|
this.pendingInputsById.delete(sourceMessageId);
|
|
710
|
+
this.pendingLocalInputMessageIds.delete(sourceMessageId);
|
|
555
711
|
}
|
|
556
712
|
}
|
|
557
713
|
else if (type === agent_messages_js_1.agentTurnEndedType || type === agent_messages_js_1.agentThreadClearedType) {
|
|
558
714
|
this.pendingInputsById.clear();
|
|
559
|
-
|
|
560
|
-
|
|
715
|
+
this.pendingLocalInputMessageIds.clear();
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
appendRenderableMessage(event) {
|
|
719
|
+
const message = event.message;
|
|
720
|
+
if (message.type === agent_messages_js_1.agentTurnEndedType) {
|
|
721
|
+
if (message.error != null) {
|
|
722
|
+
this.appendMessage(event);
|
|
561
723
|
}
|
|
724
|
+
return;
|
|
562
725
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
726
|
+
if (message.type === agent_messages_js_1.agentThreadStartType || message.type === agent_messages_js_1.agentTurnStartType || message.type === agent_messages_js_1.agentTurnSteerType) {
|
|
727
|
+
if (agentInputText(message.content).trim() !== "") {
|
|
728
|
+
this.appendMessage(event);
|
|
729
|
+
}
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
if (message.type === agent_messages_js_1.agentTurnStartAcceptedType || message.type === agent_messages_js_1.agentTurnSteerAcceptedType) {
|
|
733
|
+
const sourceMessageId = normalizedString(sourceMessageIdFor(message));
|
|
734
|
+
if (sourceMessageId != null && this.localAgentMessageIds.has(sourceMessageId)) {
|
|
735
|
+
this.pendingLocalInputMessageIds.delete(sourceMessageId);
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
if (agentInputText(message.content).trim() !== "") {
|
|
739
|
+
this.appendMessage(event, { beforePendingLocalInputs: true });
|
|
740
|
+
}
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
if (isMergeableDelta(message)) {
|
|
744
|
+
this.appendOrMergeDelta(event);
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
if (message.type === agent_messages_js_1.agentImageGenerationPartialType || message.type === agent_messages_js_1.agentImageGenerationCompletedType) {
|
|
748
|
+
const itemId = normalizedString(message.itemId);
|
|
749
|
+
if (itemId != null) {
|
|
750
|
+
this.upsertItemMessage(`image_generation:${itemId}`, event);
|
|
751
|
+
}
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
if (message instanceof agent_messages_js_1.AgentClientToolCallRequested) {
|
|
755
|
+
this.appendMessage(event);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
appendMessage(event, { beforePendingLocalInputs = false } = {}) {
|
|
759
|
+
const normalizedMessageId = normalizedString(event.message.messageId);
|
|
760
|
+
if (normalizedMessageId == null || this.messageIndexes.has(normalizedMessageId)) {
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
if (beforePendingLocalInputs) {
|
|
764
|
+
const insertIndex = this._messages.findIndex((existing) => this.pendingLocalInputMessageIds.has(existing.message.messageId));
|
|
765
|
+
if (insertIndex >= 0) {
|
|
766
|
+
this._messages.splice(insertIndex, 0, event);
|
|
767
|
+
this.indexMessagesFrom(insertIndex);
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
this.messageIndexes.set(normalizedMessageId, this._messages.length);
|
|
772
|
+
this._messages.push(event);
|
|
773
|
+
}
|
|
774
|
+
upsertItemMessage(key, event) {
|
|
775
|
+
const existingIndex = this.messageIndexes.get(key);
|
|
776
|
+
if (existingIndex == null) {
|
|
777
|
+
this.messageIndexes.set(key, this._messages.length);
|
|
778
|
+
this._messages.push(event);
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
this._messages[existingIndex] = event;
|
|
782
|
+
}
|
|
783
|
+
appendOrMergeDelta(event) {
|
|
784
|
+
const message = event.message;
|
|
785
|
+
const normalizedMessageId = normalizedString(message.messageId);
|
|
786
|
+
if (normalizedMessageId != null) {
|
|
787
|
+
if (this.mergedDeltaMessageIds.has(normalizedMessageId)) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
this.mergedDeltaMessageIds.add(normalizedMessageId);
|
|
791
|
+
}
|
|
792
|
+
const itemId = normalizedString(message.itemId);
|
|
793
|
+
if (itemId == null) {
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
const key = `${message.type}:${itemId}`;
|
|
797
|
+
const existingIndex = this.messageIndexes.get(key);
|
|
798
|
+
if (existingIndex == null) {
|
|
799
|
+
this.messageIndexes.set(key, this._messages.length);
|
|
800
|
+
this._messages.push(event);
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
const existing = this._messages[existingIndex].message;
|
|
804
|
+
const merged = mergeDeltaMessage(existing, message);
|
|
805
|
+
if (merged != null) {
|
|
806
|
+
this._messages[existingIndex] = new AgentMessageEvent({ message: merged, attachment: event.attachment });
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
indexMessagesFrom(start) {
|
|
810
|
+
for (let index = Math.max(0, start); index < this._messages.length; index += 1) {
|
|
811
|
+
const key = messageIndexKey(this._messages[index].message);
|
|
812
|
+
if (key != null) {
|
|
813
|
+
this.messageIndexes.set(key, index);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
applyActiveModel(response) {
|
|
818
|
+
for (const provider of response.providers) {
|
|
819
|
+
for (const model of provider.models) {
|
|
820
|
+
if (!model.active) {
|
|
821
|
+
continue;
|
|
822
|
+
}
|
|
823
|
+
this.currentModelValue = new agent_messages_js_1.AgentModelChanged({
|
|
824
|
+
threadId: this.threadPath,
|
|
825
|
+
sourceMessageId: response.sourceMessageId,
|
|
826
|
+
backend: provider.backend,
|
|
827
|
+
provider: provider.name,
|
|
828
|
+
model: model.name,
|
|
829
|
+
voice: model.defaultOutputVoice,
|
|
830
|
+
inputFormat: model.inputFormat,
|
|
831
|
+
outputFormat: model.outputFormat,
|
|
832
|
+
turnDetection: model.turnDetection,
|
|
833
|
+
realtimeProtocols: model.realtimeProtocols,
|
|
834
|
+
outputModalities: model.modalities.length > 0 ? [model.modalities[0]] : ["text"],
|
|
835
|
+
});
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
573
838
|
}
|
|
574
|
-
this.notifyListeners();
|
|
575
839
|
}
|
|
576
840
|
markClosed({ notify = true } = {}) {
|
|
577
841
|
this.openState = false;
|
|
@@ -636,6 +900,74 @@ function sourceMessageIdFor(message) {
|
|
|
636
900
|
const value = "sourceMessageId" in message ? message.sourceMessageId : undefined;
|
|
637
901
|
return typeof value === "string" ? value : undefined;
|
|
638
902
|
}
|
|
903
|
+
function threadMessageValue(message, key) {
|
|
904
|
+
const value = message[key];
|
|
905
|
+
return typeof value === "string" ? value : undefined;
|
|
906
|
+
}
|
|
907
|
+
function agentInputText(content) {
|
|
908
|
+
if (!Array.isArray(content)) {
|
|
909
|
+
return "";
|
|
910
|
+
}
|
|
911
|
+
return content
|
|
912
|
+
.filter((entry) => (typeof entry === "object" &&
|
|
913
|
+
entry !== null &&
|
|
914
|
+
"type" in entry &&
|
|
915
|
+
entry.type === "text" &&
|
|
916
|
+
"text" in entry &&
|
|
917
|
+
typeof entry.text === "string"))
|
|
918
|
+
.map((entry) => entry.text)
|
|
919
|
+
.join("");
|
|
920
|
+
}
|
|
921
|
+
function isMergeableDelta(message) {
|
|
922
|
+
return message.type === agent_messages_js_1.agentAudioGenerationDeltaType ||
|
|
923
|
+
message.type === agent_messages_js_1.agentAudioTranscriptionDeltaType ||
|
|
924
|
+
message.type === agent_messages_js_1.agentFileContentDeltaType ||
|
|
925
|
+
message.type === agent_messages_js_1.agentReasoningContentDeltaType ||
|
|
926
|
+
message.type === agent_messages_js_1.agentTextContentDeltaType ||
|
|
927
|
+
message.type === agent_messages_js_1.agentToolCallArgumentsDeltaType ||
|
|
928
|
+
message.type === agent_messages_js_1.agentToolCallLogDeltaType;
|
|
929
|
+
}
|
|
930
|
+
function messageIndexKey(message) {
|
|
931
|
+
if (isMergeableDelta(message)) {
|
|
932
|
+
const itemId = normalizedString(message.itemId);
|
|
933
|
+
return itemId == null ? undefined : `${message.type}:${itemId}`;
|
|
934
|
+
}
|
|
935
|
+
return normalizedString(message.messageId);
|
|
936
|
+
}
|
|
937
|
+
function mergeDeltaMessage(existing, incoming) {
|
|
938
|
+
if (existing.type !== incoming.type) {
|
|
939
|
+
return undefined;
|
|
940
|
+
}
|
|
941
|
+
if (existing.type === agent_messages_js_1.agentAudioGenerationDeltaType && existing instanceof agent_messages_js_1.AgentAudioGenerationDelta && incoming instanceof agent_messages_js_1.AgentAudioGenerationDelta) {
|
|
942
|
+
const data = new Uint8Array(existing.data.length + incoming.data.length);
|
|
943
|
+
data.set(existing.data, 0);
|
|
944
|
+
data.set(incoming.data, existing.data.length);
|
|
945
|
+
return new agent_messages_js_1.AgentAudioGenerationDelta({ ...existing.toJson(), data });
|
|
946
|
+
}
|
|
947
|
+
if (existing.type === agent_messages_js_1.agentAudioTranscriptionDeltaType && existing instanceof agent_messages_js_1.AgentAudioTranscriptionDelta && incoming instanceof agent_messages_js_1.AgentAudioTranscriptionDelta) {
|
|
948
|
+
return new agent_messages_js_1.AgentAudioTranscriptionDelta({ ...existing.toJson(), text: `${existing.text}${incoming.text}` });
|
|
949
|
+
}
|
|
950
|
+
if (existing.type === agent_messages_js_1.agentFileContentDeltaType && incoming instanceof agent_messages_js_1.AgentFileContentDelta) {
|
|
951
|
+
return incoming;
|
|
952
|
+
}
|
|
953
|
+
if (existing.type === agent_messages_js_1.agentReasoningContentDeltaType && existing instanceof agent_messages_js_1.AgentReasoningContentDelta && incoming instanceof agent_messages_js_1.AgentReasoningContentDelta) {
|
|
954
|
+
return new agent_messages_js_1.AgentReasoningContentDelta({ ...existing.toJson(), text: `${existing.text}${incoming.text}` });
|
|
955
|
+
}
|
|
956
|
+
if (existing.type === agent_messages_js_1.agentTextContentDeltaType && existing instanceof agent_messages_js_1.AgentTextContentDelta && incoming instanceof agent_messages_js_1.AgentTextContentDelta) {
|
|
957
|
+
return new agent_messages_js_1.AgentTextContentDelta({ ...existing.toJson(), text: `${existing.text}${incoming.text}` });
|
|
958
|
+
}
|
|
959
|
+
if (existing.type === agent_messages_js_1.agentToolCallArgumentsDeltaType && existing instanceof agent_messages_js_1.AgentToolCallArgumentsDelta && incoming instanceof agent_messages_js_1.AgentToolCallArgumentsDelta) {
|
|
960
|
+
return new agent_messages_js_1.AgentToolCallArgumentsDelta({ ...existing.toJson(), delta: `${existing.delta}${incoming.delta}` });
|
|
961
|
+
}
|
|
962
|
+
if (existing.type === agent_messages_js_1.agentToolCallLogDeltaType && existing instanceof agent_messages_js_1.AgentToolCallLogDelta && incoming instanceof agent_messages_js_1.AgentToolCallLogDelta) {
|
|
963
|
+
return new agent_messages_js_1.AgentToolCallLogDelta({ ...existing.toJson(), lines: [...existing.lines, ...incoming.lines] });
|
|
964
|
+
}
|
|
965
|
+
return undefined;
|
|
966
|
+
}
|
|
967
|
+
function normalizedString(value) {
|
|
968
|
+
const normalized = value?.trim();
|
|
969
|
+
return normalized == null || normalized === "" ? undefined : normalized;
|
|
970
|
+
}
|
|
639
971
|
function nonEmptyTrimmed(value) {
|
|
640
972
|
const normalized = value?.trim();
|
|
641
973
|
return normalized == null || normalized === "" ? undefined : normalized;
|