agentgui 1.0.64 → 1.0.65
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/server.js +7 -5
- package/static/app.js +58 -72
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -199,7 +199,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
199
199
|
const idempotencyKey = body.idempotencyKey || null;
|
|
200
200
|
const message = queries.createMessage(conversationId, 'user', body.content, idempotencyKey);
|
|
201
201
|
queries.createEvent('message.created', { role: 'user', messageId: message.id }, conversationId);
|
|
202
|
-
broadcastSync({ type: 'message_created', conversationId, message });
|
|
202
|
+
broadcastSync({ type: 'message_created', conversationId, message, timestamp: Date.now() });
|
|
203
203
|
const session = queries.createSession(conversationId);
|
|
204
204
|
queries.createEvent('session.created', { messageId: message.id, sessionId: session.id }, conversationId, session.id);
|
|
205
205
|
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
@@ -475,12 +475,14 @@ async function processMessage(conversationId, messageId, sessionId, content, age
|
|
|
475
475
|
});
|
|
476
476
|
queries.createEvent('session.completed', { messageId: assistantMessage.id }, conversationId, sessionId);
|
|
477
477
|
|
|
478
|
-
// Broadcast final consolidated response
|
|
478
|
+
// Broadcast final consolidated response with full message content
|
|
479
479
|
broadcastSync({
|
|
480
480
|
type: 'session_updated',
|
|
481
481
|
sessionId,
|
|
482
|
+
conversationId,
|
|
482
483
|
status: 'completed',
|
|
483
|
-
message: assistantMessage
|
|
484
|
+
message: assistantMessage,
|
|
485
|
+
timestamp: Date.now()
|
|
484
486
|
});
|
|
485
487
|
|
|
486
488
|
// STATE: PROCESSING → COMPLETED
|
|
@@ -510,10 +512,10 @@ async function processMessage(conversationId, messageId, sessionId, content, age
|
|
|
510
512
|
|
|
511
513
|
// Save error to database
|
|
512
514
|
const errorMsg = `ACP Error: ${acpError.message}`;
|
|
513
|
-
queries.createMessage(conversationId, 'assistant', errorMsg);
|
|
515
|
+
const errorMessage = queries.createMessage(conversationId, 'assistant', errorMsg);
|
|
514
516
|
queries.updateSession(sessionId, { status: 'error', error: acpError.message, completed_at: Date.now() });
|
|
515
517
|
queries.createEvent('session.error', { error: acpError.message, stack: acpError.stack }, conversationId, sessionId);
|
|
516
|
-
broadcastSync({ type: 'session_updated', sessionId, status: 'error', error: acpError.message });
|
|
518
|
+
broadcastSync({ type: 'session_updated', sessionId, conversationId, status: 'error', error: acpError.message, message: errorMessage, timestamp: Date.now() });
|
|
517
519
|
|
|
518
520
|
// Clean up ACP connection on error
|
|
519
521
|
acpPool.delete(actualAgentId);
|
package/static/app.js
CHANGED
|
@@ -265,14 +265,14 @@ class GMGUIApp {
|
|
|
265
265
|
|
|
266
266
|
handleSyncEvent(event, fromBroadcast = false) {
|
|
267
267
|
// CRITICAL: Server is the authoritative source of truth
|
|
268
|
-
//
|
|
269
|
-
//
|
|
270
|
-
|
|
268
|
+
// Real-time WebSocket events for messages arrive immediately
|
|
269
|
+
// Subscribe to conversation to receive message updates
|
|
270
|
+
|
|
271
271
|
console.log('[STATE SYNC] Event received:', event.type);
|
|
272
|
-
|
|
272
|
+
|
|
273
273
|
switch (event.type) {
|
|
274
274
|
case 'sync_connected':
|
|
275
|
-
console.log('[STATE SYNC] Connected to sync bus -
|
|
275
|
+
console.log('[STATE SYNC] Connected to sync bus - subscribing to all active sessions');
|
|
276
276
|
// On connection, always do a full state refresh
|
|
277
277
|
this.fetchConversations().then(() => this.renderChatHistory());
|
|
278
278
|
break;
|
|
@@ -325,32 +325,54 @@ class GMGUIApp {
|
|
|
325
325
|
break;
|
|
326
326
|
|
|
327
327
|
case 'message_created':
|
|
328
|
-
console.log('[STATE SYNC] Message created
|
|
329
|
-
//
|
|
330
|
-
this.
|
|
331
|
-
|
|
332
|
-
//
|
|
333
|
-
|
|
334
|
-
|
|
328
|
+
console.log('[STATE SYNC] Message created via WebSocket - real-time push');
|
|
329
|
+
// User message was created - add it immediately without polling
|
|
330
|
+
if (this.currentConversation === event.conversationId && event.message) {
|
|
331
|
+
console.log('[STATE SYNC] Adding user message to display immediately');
|
|
332
|
+
// Stop any existing polling for this conversation
|
|
333
|
+
this.stopPollingMessages();
|
|
334
|
+
// Add message directly to display
|
|
335
|
+
this.addMessageToDisplay(event.message);
|
|
336
|
+
// Update conversation metadata
|
|
337
|
+
this.fetchConversations().then(() => this.renderChatHistory());
|
|
338
|
+
// Auto-scroll to new message
|
|
339
|
+
if (this.settings.autoScroll) {
|
|
340
|
+
setTimeout(() => {
|
|
341
|
+
const div = document.getElementById('chatMessages');
|
|
342
|
+
if (div) div.scrollTop = div.scrollHeight;
|
|
343
|
+
}, 50);
|
|
335
344
|
}
|
|
336
|
-
}
|
|
345
|
+
} else {
|
|
346
|
+
// Not viewing this conversation, just update timestamps
|
|
347
|
+
this.fetchConversations().then(() => this.renderChatHistory());
|
|
348
|
+
}
|
|
337
349
|
if (!fromBroadcast && this.broadcastChannel) {
|
|
338
350
|
this.broadcastChannel.postMessage(event);
|
|
339
351
|
}
|
|
340
352
|
break;
|
|
341
353
|
|
|
342
354
|
case 'session_updated':
|
|
343
|
-
console.log('[STATE SYNC] Session updated:', event.status, '-
|
|
344
|
-
// Session completed
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
//
|
|
350
|
-
|
|
351
|
-
|
|
355
|
+
console.log('[STATE SYNC] Session updated via WebSocket:', event.status, '- real-time push');
|
|
356
|
+
// Session completed - agent response arrived via WebSocket push (no polling!)
|
|
357
|
+
if (this.currentConversation === event.conversationId && event.message) {
|
|
358
|
+
console.log('[STATE SYNC] Adding assistant message to display immediately (real-time push)');
|
|
359
|
+
// Stop polling immediately
|
|
360
|
+
this.stopPollingMessages();
|
|
361
|
+
// Add message directly to display
|
|
362
|
+
this.addMessageToDisplay(event.message);
|
|
363
|
+
// Update conversation metadata
|
|
364
|
+
this.fetchConversations().then(() => this.renderChatHistory());
|
|
365
|
+
// Auto-scroll to new message
|
|
366
|
+
if (this.settings.autoScroll) {
|
|
367
|
+
setTimeout(() => {
|
|
368
|
+
const div = document.getElementById('chatMessages');
|
|
369
|
+
if (div) div.scrollTop = div.scrollHeight;
|
|
370
|
+
}, 50);
|
|
352
371
|
}
|
|
353
|
-
}
|
|
372
|
+
} else {
|
|
373
|
+
// Not viewing this conversation, just update timestamps
|
|
374
|
+
this.fetchConversations().then(() => this.renderChatHistory());
|
|
375
|
+
}
|
|
354
376
|
if (!fromBroadcast && this.broadcastChannel) {
|
|
355
377
|
this.broadcastChannel.postMessage(event);
|
|
356
378
|
}
|
|
@@ -1350,56 +1372,20 @@ class GMGUIApp {
|
|
|
1350
1372
|
this.addMessageToDisplay({ role: 'system', content: text });
|
|
1351
1373
|
}
|
|
1352
1374
|
|
|
1353
|
-
|
|
1354
|
-
if (this.pollingInterval)
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
.map(el => el.dataset.messageId)
|
|
1361
|
-
.filter(id => id && !id.startsWith('pending-'))
|
|
1362
|
-
);
|
|
1363
|
-
|
|
1364
|
-
this.pollingInterval = setInterval(async () => {
|
|
1365
|
-
try {
|
|
1366
|
-
const res = await this.apiFetch(`${BASE_URL}/api/conversations/${conversationId}/messages`);
|
|
1367
|
-
const data = await res.json();
|
|
1368
|
-
const messages = data.messages || [];
|
|
1369
|
-
|
|
1370
|
-
let added = false;
|
|
1371
|
-
messages.forEach(msg => {
|
|
1372
|
-
if (msg.id && !lastKnownIds.has(msg.id)) {
|
|
1373
|
-
const existingEl = document.querySelector(`[data-message-id="${msg.id}"]`);
|
|
1374
|
-
if (!existingEl) {
|
|
1375
|
-
this.addMessageToDisplay(msg);
|
|
1376
|
-
added = true;
|
|
1377
|
-
}
|
|
1378
|
-
lastKnownIds.add(msg.id);
|
|
1379
|
-
}
|
|
1380
|
-
});
|
|
1381
|
-
if (added) {
|
|
1382
|
-
pollCount = 0;
|
|
1383
|
-
|
|
1384
|
-
if (this.settings.autoScroll) {
|
|
1385
|
-
const div = document.getElementById('chatMessages');
|
|
1386
|
-
if (div) div.scrollTop = div.scrollHeight;
|
|
1387
|
-
}
|
|
1388
|
-
} else {
|
|
1389
|
-
pollCount++;
|
|
1390
|
-
}
|
|
1375
|
+
stopPollingMessages() {
|
|
1376
|
+
if (this.pollingInterval) {
|
|
1377
|
+
clearInterval(this.pollingInterval);
|
|
1378
|
+
this.pollingInterval = null;
|
|
1379
|
+
console.log('[POLLING] Polling stopped - using WebSocket push instead');
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1391
1382
|
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
console.error('Polling error:', e);
|
|
1399
|
-
clearInterval(this.pollingInterval);
|
|
1400
|
-
this.pollingInterval = null;
|
|
1401
|
-
}
|
|
1402
|
-
}, 500); // Poll every 500ms
|
|
1383
|
+
startPollingMessages(conversationId) {
|
|
1384
|
+
// DEPRECATED: Polling mechanism replaced with WebSocket push
|
|
1385
|
+
// This method is kept for backwards compatibility but does nothing
|
|
1386
|
+
// Messages now arrive via WebSocket in real-time via handleSyncEvent
|
|
1387
|
+
console.log('[POLLING] Polling requested but disabled - WebSocket handles real-time updates');
|
|
1388
|
+
this.stopPollingMessages();
|
|
1403
1389
|
}
|
|
1404
1390
|
|
|
1405
1391
|
createThoughtBlock() {
|