agentgui 1.0.595 → 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 +53 -0
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;
|
|
@@ -2525,6 +2529,55 @@ class AgentGUIClient {
|
|
|
2525
2529
|
this.conversationCache.delete(conversationId);
|
|
2526
2530
|
}
|
|
2527
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
|
+
|
|
2528
2581
|
async loadConversationMessages(conversationId) {
|
|
2529
2582
|
try {
|
|
2530
2583
|
if (this._previousConvAbort) {
|