agentgui 1.0.546 → 1.0.548
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 +118 -16
package/package.json
CHANGED
package/static/js/client.js
CHANGED
|
@@ -35,6 +35,16 @@ class AgentGUIClient {
|
|
|
35
35
|
this.conversationCache = new Map();
|
|
36
36
|
this.MAX_CACHE_SIZE = 10;
|
|
37
37
|
|
|
38
|
+
// Conversation list cache with TTL
|
|
39
|
+
this.conversationListCache = {
|
|
40
|
+
data: [],
|
|
41
|
+
timestamp: 0,
|
|
42
|
+
ttl: 30000 // 30 seconds
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Draft prompts per conversation
|
|
46
|
+
this.draftPrompts = new Map();
|
|
47
|
+
|
|
38
48
|
// Event handlers
|
|
39
49
|
this.eventHandlers = {};
|
|
40
50
|
|
|
@@ -155,12 +165,16 @@ class AgentGUIClient {
|
|
|
155
165
|
this.updateConnectionStatus('connected');
|
|
156
166
|
this._subscribeToConversationUpdates();
|
|
157
167
|
this._recoverMissedChunks();
|
|
168
|
+
this.updateSendButtonState();
|
|
169
|
+
this.enablePromptArea();
|
|
158
170
|
this.emit('ws:connected');
|
|
159
171
|
});
|
|
160
172
|
|
|
161
173
|
this.wsManager.on('disconnected', () => {
|
|
162
174
|
console.log('WebSocket disconnected');
|
|
163
175
|
this.updateConnectionStatus('disconnected');
|
|
176
|
+
this.updateSendButtonState();
|
|
177
|
+
this.disablePromptArea();
|
|
164
178
|
this.emit('ws:disconnected');
|
|
165
179
|
});
|
|
166
180
|
|
|
@@ -194,10 +208,16 @@ class AgentGUIClient {
|
|
|
194
208
|
// Switch to idle view when selecting non-streaming conversation
|
|
195
209
|
window.addEventListener('conversation-selected', (e) => {
|
|
196
210
|
const convId = e.detail.conversationId;
|
|
211
|
+
// Save draft from previous conversation before switching
|
|
212
|
+
this.saveDraftPrompt();
|
|
213
|
+
|
|
197
214
|
const isStreaming = convId && this.state.streamingConversations.has(convId);
|
|
198
215
|
if (!isStreaming && window.switchView) {
|
|
199
216
|
window.switchView('chat');
|
|
200
217
|
}
|
|
218
|
+
|
|
219
|
+
// Restore draft for new conversation after a tick
|
|
220
|
+
setTimeout(() => this.restoreDraftPrompt(convId), 0);
|
|
201
221
|
});
|
|
202
222
|
|
|
203
223
|
// Preserve controls state across tab switches
|
|
@@ -392,6 +412,19 @@ class AgentGUIClient {
|
|
|
392
412
|
this.ui.agentSelector = document.querySelector('[data-agent-selector]');
|
|
393
413
|
this.ui.modelSelector = document.querySelector('[data-model-selector]');
|
|
394
414
|
|
|
415
|
+
// Auto-save drafts on input
|
|
416
|
+
if (this.ui.messageInput) {
|
|
417
|
+
this.ui.messageInput.addEventListener('input', () => {
|
|
418
|
+
this.saveDraftPrompt();
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
// Restore draft when conversation loads
|
|
422
|
+
const currentConvId = this.state.currentConversation?.id;
|
|
423
|
+
if (currentConvId) {
|
|
424
|
+
this.restoreDraftPrompt(currentConvId);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
395
428
|
if (this.ui.cliSelector) {
|
|
396
429
|
this.ui.cliSelector.addEventListener('change', () => {
|
|
397
430
|
if (!this._agentLocked) {
|
|
@@ -2140,10 +2173,21 @@ class AgentGUIClient {
|
|
|
2140
2173
|
* Load conversations
|
|
2141
2174
|
*/
|
|
2142
2175
|
async loadConversations() {
|
|
2176
|
+
// Return cached conversations if still fresh
|
|
2177
|
+
const now = Date.now();
|
|
2178
|
+
if (this.conversationListCache.data.length > 0 &&
|
|
2179
|
+
(now - this.conversationListCache.timestamp) < this.conversationListCache.ttl) {
|
|
2180
|
+
this.state.conversations = this.conversationListCache.data;
|
|
2181
|
+
return this.conversationListCache.data;
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2143
2184
|
return this._dedupedFetch('loadConversations', async () => {
|
|
2144
2185
|
try {
|
|
2145
2186
|
const { conversations } = await window.wsClient.rpc('conv.ls');
|
|
2146
2187
|
this.state.conversations = conversations;
|
|
2188
|
+
// Update cache
|
|
2189
|
+
this.conversationListCache.data = conversations;
|
|
2190
|
+
this.conversationListCache.timestamp = Date.now();
|
|
2147
2191
|
return conversations;
|
|
2148
2192
|
} catch (error) {
|
|
2149
2193
|
console.error('Failed to load conversations:', error);
|
|
@@ -2284,33 +2328,23 @@ class AgentGUIClient {
|
|
|
2284
2328
|
|
|
2285
2329
|
/**
|
|
2286
2330
|
* Disable UI controls during streaming
|
|
2331
|
+
* NOTE: Only disables stop button visibility. Prompt, input, and inject remain enabled.
|
|
2287
2332
|
*/
|
|
2288
2333
|
disableControls() {
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
}
|
|
2292
|
-
if (this.ui.sendButton) {
|
|
2293
|
-
this.ui.sendButton.disabled = true;
|
|
2294
|
-
}
|
|
2295
|
-
const injectBtn = document.getElementById('injectBtn');
|
|
2334
|
+
// Prompt area and inject button are NEVER disabled during streaming
|
|
2335
|
+
// Only stop button behavior changes
|
|
2296
2336
|
const stopBtn = document.getElementById('stopBtn');
|
|
2297
|
-
if (injectBtn) injectBtn.disabled = true;
|
|
2298
2337
|
if (stopBtn) stopBtn.disabled = false;
|
|
2299
2338
|
}
|
|
2300
2339
|
|
|
2301
2340
|
/**
|
|
2302
2341
|
* Enable UI controls
|
|
2342
|
+
* NOTE: Restores stop button visibility. Prompt area always stays enabled.
|
|
2303
2343
|
*/
|
|
2304
2344
|
enableControls() {
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
}
|
|
2308
|
-
if (this.ui.sendButton) {
|
|
2309
|
-
this.ui.sendButton.disabled = false;
|
|
2310
|
-
}
|
|
2311
|
-
const injectBtn = document.getElementById('injectBtn');
|
|
2345
|
+
// Prompt area and inject button are always enabled unless disconnected
|
|
2346
|
+
// Only stop button behavior changes
|
|
2312
2347
|
const stopBtn = document.getElementById('stopBtn');
|
|
2313
|
-
if (injectBtn) injectBtn.disabled = false;
|
|
2314
2348
|
if (stopBtn) stopBtn.disabled = true;
|
|
2315
2349
|
}
|
|
2316
2350
|
|
|
@@ -2874,6 +2908,74 @@ class AgentGUIClient {
|
|
|
2874
2908
|
};
|
|
2875
2909
|
}
|
|
2876
2910
|
|
|
2911
|
+
/**
|
|
2912
|
+
* Save draft prompt for current conversation
|
|
2913
|
+
*/
|
|
2914
|
+
saveDraftPrompt() {
|
|
2915
|
+
const convId = this.state.currentConversation?.id;
|
|
2916
|
+
if (convId && this.ui.messageInput) {
|
|
2917
|
+
const draft = this.ui.messageInput.value;
|
|
2918
|
+
this.draftPrompts.set(convId, draft);
|
|
2919
|
+
if (draft) {
|
|
2920
|
+
localStorage.setItem(`draft-${convId}`, draft);
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
|
|
2925
|
+
/**
|
|
2926
|
+
* Restore draft prompt for conversation
|
|
2927
|
+
*/
|
|
2928
|
+
restoreDraftPrompt(conversationId) {
|
|
2929
|
+
if (!this.ui.messageInput) return;
|
|
2930
|
+
|
|
2931
|
+
let draft = this.draftPrompts.get(conversationId) || '';
|
|
2932
|
+
if (!draft) {
|
|
2933
|
+
draft = localStorage.getItem(`draft-${conversationId}`) || '';
|
|
2934
|
+
if (draft) this.draftPrompts.set(conversationId, draft);
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
this.ui.messageInput.value = draft;
|
|
2938
|
+
}
|
|
2939
|
+
|
|
2940
|
+
/**
|
|
2941
|
+
* Clear draft for conversation
|
|
2942
|
+
*/
|
|
2943
|
+
clearDraft(conversationId) {
|
|
2944
|
+
this.draftPrompts.delete(conversationId);
|
|
2945
|
+
localStorage.removeItem(`draft-${conversationId}`);
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2948
|
+
/**
|
|
2949
|
+
* Update send button state based on WebSocket connection
|
|
2950
|
+
*/
|
|
2951
|
+
updateSendButtonState() {
|
|
2952
|
+
if (this.ui.sendButton) {
|
|
2953
|
+
this.ui.sendButton.disabled = !this.wsManager.isConnected;
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
/**
|
|
2958
|
+
* Disable prompt area (input and inject button) only on disconnect
|
|
2959
|
+
*/
|
|
2960
|
+
disablePromptArea() {
|
|
2961
|
+
if (this.ui.messageInput) {
|
|
2962
|
+
this.ui.messageInput.disabled = true;
|
|
2963
|
+
}
|
|
2964
|
+
const injectBtn = document.getElementById('injectBtn');
|
|
2965
|
+
if (injectBtn) injectBtn.disabled = true;
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
/**
|
|
2969
|
+
* Enable prompt area (input and inject button) on connect
|
|
2970
|
+
*/
|
|
2971
|
+
enablePromptArea() {
|
|
2972
|
+
if (this.ui.messageInput) {
|
|
2973
|
+
this.ui.messageInput.disabled = false;
|
|
2974
|
+
}
|
|
2975
|
+
const injectBtn = document.getElementById('injectBtn');
|
|
2976
|
+
if (injectBtn) injectBtn.disabled = false;
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2877
2979
|
/**
|
|
2878
2980
|
* Cleanup resources
|
|
2879
2981
|
*/
|