agentgui 1.0.594 → 1.0.596
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/lib/ws-handlers-conv.js +0 -1
- package/package.json +1 -1
- package/static/js/client.js +67 -10
package/lib/ws-handlers-conv.js
CHANGED
|
@@ -104,7 +104,6 @@ export function register(router, deps) {
|
|
|
104
104
|
if (!conv) notFound('Conversation not found');
|
|
105
105
|
if (!p.content) fail(400, 'Missing content');
|
|
106
106
|
const entry = activeExecutions.get(p.id);
|
|
107
|
-
if (entry && p.eager) fail(409, 'Cannot eagerly inject while execution is running - message queued');
|
|
108
107
|
const message = queries.createMessage(p.id, 'user', '[INJECTED] ' + p.content);
|
|
109
108
|
if (!entry) {
|
|
110
109
|
const agentId = conv.agentId || 'claude-code';
|
package/package.json
CHANGED
package/static/js/client.js
CHANGED
|
@@ -79,6 +79,10 @@ class AgentGUIClient {
|
|
|
79
79
|
this._inflightRequests = new Map();
|
|
80
80
|
this._previousConvAbort = null;
|
|
81
81
|
|
|
82
|
+
// PHASE 2: Request Lifetime Tracking
|
|
83
|
+
this._loadInProgress = {}; // { [conversationId]: { requestId, abortController, timestamp, prevConversationId } }
|
|
84
|
+
this._currentRequestId = 0; // Auto-incrementing request counter
|
|
85
|
+
|
|
82
86
|
this._scrollKalman = typeof KalmanFilter !== 'undefined' ? new KalmanFilter({ processNoise: 50, measurementNoise: 100 }) : null;
|
|
83
87
|
this._scrollTarget = 0;
|
|
84
88
|
this._scrollAnimating = false;
|
|
@@ -491,17 +495,21 @@ class AgentGUIClient {
|
|
|
491
495
|
this.showError('Please enter a message to steer');
|
|
492
496
|
return;
|
|
493
497
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
}
|
|
501
|
-
} catch (err) {
|
|
502
|
-
console.error('Failed to steer:', err);
|
|
503
|
-
this.showError('Failed to steer: ' + err.message);
|
|
498
|
+
|
|
499
|
+
// Capture message and clear UI immediately (no await)
|
|
500
|
+
const steerMsg = message;
|
|
501
|
+
if (this.ui.messageInput) {
|
|
502
|
+
this.ui.messageInput.value = '';
|
|
503
|
+
this.ui.messageInput.style.height = 'auto';
|
|
504
504
|
}
|
|
505
|
+
|
|
506
|
+
// Fire RPC in background, don't await
|
|
507
|
+
window.wsClient.rpc('conv.steer', { id: this.state.currentConversation.id, content: steerMsg })
|
|
508
|
+
.then(data => console.log('Steer response:', data))
|
|
509
|
+
.catch(err => {
|
|
510
|
+
console.error('Failed to steer:', err);
|
|
511
|
+
this.showError('Failed to steer: ' + err.message);
|
|
512
|
+
});
|
|
505
513
|
} else {
|
|
506
514
|
const instructions = await window.UIDialog.prompt('Enter instructions to inject into the running agent:', '', 'Inject Instructions');
|
|
507
515
|
if (!instructions) return;
|
|
@@ -2521,6 +2529,55 @@ class AgentGUIClient {
|
|
|
2521
2529
|
this.conversationCache.delete(conversationId);
|
|
2522
2530
|
}
|
|
2523
2531
|
|
|
2532
|
+
/**
|
|
2533
|
+
* PHASE 2: Create a new load request with lifetime tracking
|
|
2534
|
+
* Assigns unique requestId, tracks in _loadInProgress, returns abort signal
|
|
2535
|
+
* Automatically cancels previous loads to this conversation
|
|
2536
|
+
*/
|
|
2537
|
+
_makeLoadRequest(conversationId) {
|
|
2538
|
+
const requestId = ++this._currentRequestId;
|
|
2539
|
+
const abortController = new AbortController();
|
|
2540
|
+
|
|
2541
|
+
// Cancel previous request to this conversation
|
|
2542
|
+
if (this._loadInProgress[conversationId]) {
|
|
2543
|
+
const prevReq = this._loadInProgress[conversationId];
|
|
2544
|
+
try {
|
|
2545
|
+
prevReq.abortController.abort();
|
|
2546
|
+
} catch (e) {}
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
this._loadInProgress[conversationId] = {
|
|
2550
|
+
requestId,
|
|
2551
|
+
abortController,
|
|
2552
|
+
timestamp: Date.now(),
|
|
2553
|
+
prevConversationId: this.state.currentConversation?.id
|
|
2554
|
+
};
|
|
2555
|
+
|
|
2556
|
+
return { requestId, abortController: abortController.signal };
|
|
2557
|
+
}
|
|
2558
|
+
|
|
2559
|
+
/**
|
|
2560
|
+
* PHASE 2: Verify request is still current before rendering
|
|
2561
|
+
* Returns true if requestId matches current load for this conversation
|
|
2562
|
+
* Returns false if newer request arrived, or request was cancelled
|
|
2563
|
+
*/
|
|
2564
|
+
_verifyRequestId(conversationId, requestId) {
|
|
2565
|
+
const current = this._loadInProgress[conversationId];
|
|
2566
|
+
if (!current) return false;
|
|
2567
|
+
if (current.requestId !== requestId) return false;
|
|
2568
|
+
return true;
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
/**
|
|
2572
|
+
* PHASE 2: Complete/cleanup a load request
|
|
2573
|
+
*/
|
|
2574
|
+
_completeLoadRequest(conversationId, requestId) {
|
|
2575
|
+
const req = this._loadInProgress[conversationId];
|
|
2576
|
+
if (req && req.requestId === requestId) {
|
|
2577
|
+
delete this._loadInProgress[conversationId];
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2524
2581
|
async loadConversationMessages(conversationId) {
|
|
2525
2582
|
try {
|
|
2526
2583
|
if (this._previousConvAbort) {
|