agentgui 1.0.140 → 1.0.141
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/package.json +1 -1
- package/static/js/client.js +104 -7
package/package.json
CHANGED
package/static/js/client.js
CHANGED
|
@@ -348,7 +348,7 @@ class AgentGUIClient {
|
|
|
348
348
|
|
|
349
349
|
switch (data.type) {
|
|
350
350
|
case 'streaming_start':
|
|
351
|
-
this.handleStreamingStart(data);
|
|
351
|
+
this.handleStreamingStart(data).catch(e => console.error('handleStreamingStart error:', e));
|
|
352
352
|
break;
|
|
353
353
|
case 'streaming_progress':
|
|
354
354
|
this.handleStreamingProgress(data);
|
|
@@ -388,7 +388,7 @@ class AgentGUIClient {
|
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
handleStreamingStart(data) {
|
|
391
|
+
async handleStreamingStart(data) {
|
|
392
392
|
console.log('Streaming started:', data);
|
|
393
393
|
|
|
394
394
|
// If this streaming event is for a different conversation than what we are viewing,
|
|
@@ -420,8 +420,60 @@ class AgentGUIClient {
|
|
|
420
420
|
if (outputEl) {
|
|
421
421
|
let messagesEl = outputEl.querySelector('.conversation-messages');
|
|
422
422
|
if (!messagesEl) {
|
|
423
|
-
|
|
423
|
+
// Load existing conversation history before starting the stream
|
|
424
|
+
const conv = this.state.currentConversation;
|
|
425
|
+
const wdInfo = conv?.workingDirectory ? ` - ${this.escapeHtml(conv.workingDirectory)}` : '';
|
|
426
|
+
outputEl.innerHTML = `
|
|
427
|
+
<div class="conversation-header">
|
|
428
|
+
<h2>${this.escapeHtml(conv?.title || 'Conversation')}</h2>
|
|
429
|
+
<p class="text-secondary">${conv?.agentType || 'unknown'} - ${new Date(conv?.created_at || Date.now()).toLocaleDateString()}${wdInfo}</p>
|
|
430
|
+
</div>
|
|
431
|
+
<div class="conversation-messages"></div>
|
|
432
|
+
`;
|
|
424
433
|
messagesEl = outputEl.querySelector('.conversation-messages');
|
|
434
|
+
// Load prior messages into the container
|
|
435
|
+
try {
|
|
436
|
+
const msgResp = await fetch(window.__BASE_URL + `/api/conversations/${data.conversationId}/messages`);
|
|
437
|
+
if (msgResp.ok) {
|
|
438
|
+
const msgData = await msgResp.json();
|
|
439
|
+
const priorChunks = await this.fetchChunks(data.conversationId, 0);
|
|
440
|
+
if (priorChunks.length > 0) {
|
|
441
|
+
const userMsgs = (msgData.messages || []).filter(m => m.role === 'user');
|
|
442
|
+
const sessionOrder = [];
|
|
443
|
+
const sessionGroups = {};
|
|
444
|
+
priorChunks.forEach(c => {
|
|
445
|
+
if (!sessionGroups[c.sessionId]) { sessionGroups[c.sessionId] = []; sessionOrder.push(c.sessionId); }
|
|
446
|
+
sessionGroups[c.sessionId].push(c);
|
|
447
|
+
});
|
|
448
|
+
let ui = 0;
|
|
449
|
+
sessionOrder.forEach(sid => {
|
|
450
|
+
const sList = sessionGroups[sid];
|
|
451
|
+
const sStart = sList[0].created_at;
|
|
452
|
+
while (ui < userMsgs.length && userMsgs[ui].created_at <= sStart) {
|
|
453
|
+
const m = userMsgs[ui++];
|
|
454
|
+
messagesEl.insertAdjacentHTML('beforeend', `<div class="message message-user" data-msg-id="${m.id}"><div class="message-role">User</div>${this.renderMessageContent(m.content)}<div class="message-timestamp">${new Date(m.created_at).toLocaleString()}</div></div>`);
|
|
455
|
+
}
|
|
456
|
+
const mDiv = document.createElement('div');
|
|
457
|
+
mDiv.className = 'message message-assistant';
|
|
458
|
+
mDiv.id = `message-${sid}`;
|
|
459
|
+
mDiv.innerHTML = '<div class="message-role">Assistant</div><div class="message-blocks streaming-blocks"></div>';
|
|
460
|
+
const bEl = mDiv.querySelector('.message-blocks');
|
|
461
|
+
sList.forEach(chunk => { if (chunk.block?.type) { const el = this.renderer.renderBlock(chunk.block, chunk); if (el) bEl.appendChild(el); } });
|
|
462
|
+
const ts = document.createElement('div'); ts.className = 'message-timestamp'; ts.textContent = new Date(sList[sList.length - 1].created_at).toLocaleString();
|
|
463
|
+
mDiv.appendChild(ts);
|
|
464
|
+
messagesEl.appendChild(mDiv);
|
|
465
|
+
});
|
|
466
|
+
while (ui < userMsgs.length) {
|
|
467
|
+
const m = userMsgs[ui++];
|
|
468
|
+
messagesEl.insertAdjacentHTML('beforeend', `<div class="message message-user" data-msg-id="${m.id}"><div class="message-role">User</div>${this.renderMessageContent(m.content)}<div class="message-timestamp">${new Date(m.created_at).toLocaleString()}</div></div>`);
|
|
469
|
+
}
|
|
470
|
+
} else {
|
|
471
|
+
messagesEl.innerHTML = this.renderMessages(msgData.messages || []);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
} catch (e) {
|
|
475
|
+
console.warn('Failed to load prior messages for streaming view:', e);
|
|
476
|
+
}
|
|
425
477
|
}
|
|
426
478
|
const streamingDiv = document.createElement('div');
|
|
427
479
|
streamingDiv.className = 'message message-assistant streaming-message';
|
|
@@ -1181,17 +1233,48 @@ class AgentGUIClient {
|
|
|
1181
1233
|
// Render all chunks
|
|
1182
1234
|
const messagesEl = outputEl.querySelector('.conversation-messages');
|
|
1183
1235
|
if (chunks.length > 0) {
|
|
1184
|
-
//
|
|
1236
|
+
// Fetch user messages to interleave with session chunks
|
|
1237
|
+
let userMessages = [];
|
|
1238
|
+
try {
|
|
1239
|
+
const msgResp = await fetch(window.__BASE_URL + `/api/conversations/${conversationId}/messages`);
|
|
1240
|
+
if (msgResp.ok) {
|
|
1241
|
+
const msgData = await msgResp.json();
|
|
1242
|
+
userMessages = (msgData.messages || []).filter(m => m.role === 'user');
|
|
1243
|
+
}
|
|
1244
|
+
} catch (_) {}
|
|
1245
|
+
|
|
1246
|
+
// Group chunks by session, preserving order
|
|
1247
|
+
const sessionOrder = [];
|
|
1185
1248
|
const sessionChunks = {};
|
|
1186
1249
|
chunks.forEach(chunk => {
|
|
1187
1250
|
if (!sessionChunks[chunk.sessionId]) {
|
|
1188
1251
|
sessionChunks[chunk.sessionId] = [];
|
|
1252
|
+
sessionOrder.push(chunk.sessionId);
|
|
1189
1253
|
}
|
|
1190
1254
|
sessionChunks[chunk.sessionId].push(chunk);
|
|
1191
1255
|
});
|
|
1192
1256
|
|
|
1193
|
-
//
|
|
1194
|
-
|
|
1257
|
+
// Build a timeline: match user messages to sessions by timestamp
|
|
1258
|
+
let userMsgIdx = 0;
|
|
1259
|
+
sessionOrder.forEach((sessionId) => {
|
|
1260
|
+
const sessionChunkList = sessionChunks[sessionId];
|
|
1261
|
+
const sessionStart = sessionChunkList[0].created_at;
|
|
1262
|
+
|
|
1263
|
+
// Render user messages that came before this session
|
|
1264
|
+
while (userMsgIdx < userMessages.length && userMessages[userMsgIdx].created_at <= sessionStart) {
|
|
1265
|
+
const msg = userMessages[userMsgIdx];
|
|
1266
|
+
const userDiv = document.createElement('div');
|
|
1267
|
+
userDiv.className = 'message message-user';
|
|
1268
|
+
userDiv.setAttribute('data-msg-id', msg.id);
|
|
1269
|
+
userDiv.innerHTML = `
|
|
1270
|
+
<div class="message-role">User</div>
|
|
1271
|
+
${this.renderMessageContent(msg.content)}
|
|
1272
|
+
<div class="message-timestamp">${new Date(msg.created_at).toLocaleString()}</div>
|
|
1273
|
+
`;
|
|
1274
|
+
messagesEl.appendChild(userDiv);
|
|
1275
|
+
userMsgIdx++;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1195
1278
|
const isCurrentActiveSession = shouldResumeStreaming && latestSession && latestSession.id === sessionId;
|
|
1196
1279
|
const messageDiv = document.createElement('div');
|
|
1197
1280
|
messageDiv.className = `message message-assistant${isCurrentActiveSession ? ' streaming-message' : ''}`;
|
|
@@ -1208,7 +1291,6 @@ class AgentGUIClient {
|
|
|
1208
1291
|
}
|
|
1209
1292
|
});
|
|
1210
1293
|
|
|
1211
|
-
// Add streaming indicator for active session
|
|
1212
1294
|
if (isCurrentActiveSession) {
|
|
1213
1295
|
const indicatorDiv = document.createElement('div');
|
|
1214
1296
|
indicatorDiv.className = 'streaming-indicator';
|
|
@@ -1227,6 +1309,21 @@ class AgentGUIClient {
|
|
|
1227
1309
|
|
|
1228
1310
|
messagesEl.appendChild(messageDiv);
|
|
1229
1311
|
});
|
|
1312
|
+
|
|
1313
|
+
// Render any remaining user messages after the last session
|
|
1314
|
+
while (userMsgIdx < userMessages.length) {
|
|
1315
|
+
const msg = userMessages[userMsgIdx];
|
|
1316
|
+
const userDiv = document.createElement('div');
|
|
1317
|
+
userDiv.className = 'message message-user';
|
|
1318
|
+
userDiv.setAttribute('data-msg-id', msg.id);
|
|
1319
|
+
userDiv.innerHTML = `
|
|
1320
|
+
<div class="message-role">User</div>
|
|
1321
|
+
${this.renderMessageContent(msg.content)}
|
|
1322
|
+
<div class="message-timestamp">${new Date(msg.created_at).toLocaleString()}</div>
|
|
1323
|
+
`;
|
|
1324
|
+
messagesEl.appendChild(userDiv);
|
|
1325
|
+
userMsgIdx++;
|
|
1326
|
+
}
|
|
1230
1327
|
} else {
|
|
1231
1328
|
// Fall back to messages if no chunks
|
|
1232
1329
|
const messagesResponse = await fetch(window.__BASE_URL + `/api/conversations/${conversationId}/messages`);
|