agentgui 1.0.546 → 1.0.547

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.546",
3
+ "version": "1.0.547",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
@@ -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,14 @@ class AgentGUIClient {
155
165
  this.updateConnectionStatus('connected');
156
166
  this._subscribeToConversationUpdates();
157
167
  this._recoverMissedChunks();
168
+ this.updateSendButtonState();
158
169
  this.emit('ws:connected');
159
170
  });
160
171
 
161
172
  this.wsManager.on('disconnected', () => {
162
173
  console.log('WebSocket disconnected');
163
174
  this.updateConnectionStatus('disconnected');
175
+ this.updateSendButtonState();
164
176
  this.emit('ws:disconnected');
165
177
  });
166
178
 
@@ -194,10 +206,16 @@ class AgentGUIClient {
194
206
  // Switch to idle view when selecting non-streaming conversation
195
207
  window.addEventListener('conversation-selected', (e) => {
196
208
  const convId = e.detail.conversationId;
209
+ // Save draft from previous conversation before switching
210
+ this.saveDraftPrompt();
211
+
197
212
  const isStreaming = convId && this.state.streamingConversations.has(convId);
198
213
  if (!isStreaming && window.switchView) {
199
214
  window.switchView('chat');
200
215
  }
216
+
217
+ // Restore draft for new conversation after a tick
218
+ setTimeout(() => this.restoreDraftPrompt(convId), 0);
201
219
  });
202
220
 
203
221
  // Preserve controls state across tab switches
@@ -392,6 +410,19 @@ class AgentGUIClient {
392
410
  this.ui.agentSelector = document.querySelector('[data-agent-selector]');
393
411
  this.ui.modelSelector = document.querySelector('[data-model-selector]');
394
412
 
413
+ // Auto-save drafts on input
414
+ if (this.ui.messageInput) {
415
+ this.ui.messageInput.addEventListener('input', () => {
416
+ this.saveDraftPrompt();
417
+ });
418
+
419
+ // Restore draft when conversation loads
420
+ const currentConvId = this.state.currentConversation?.id;
421
+ if (currentConvId) {
422
+ this.restoreDraftPrompt(currentConvId);
423
+ }
424
+ }
425
+
395
426
  if (this.ui.cliSelector) {
396
427
  this.ui.cliSelector.addEventListener('change', () => {
397
428
  if (!this._agentLocked) {
@@ -2140,10 +2171,21 @@ class AgentGUIClient {
2140
2171
  * Load conversations
2141
2172
  */
2142
2173
  async loadConversations() {
2174
+ // Return cached conversations if still fresh
2175
+ const now = Date.now();
2176
+ if (this.conversationListCache.data.length > 0 &&
2177
+ (now - this.conversationListCache.timestamp) < this.conversationListCache.ttl) {
2178
+ this.state.conversations = this.conversationListCache.data;
2179
+ return this.conversationListCache.data;
2180
+ }
2181
+
2143
2182
  return this._dedupedFetch('loadConversations', async () => {
2144
2183
  try {
2145
2184
  const { conversations } = await window.wsClient.rpc('conv.ls');
2146
2185
  this.state.conversations = conversations;
2186
+ // Update cache
2187
+ this.conversationListCache.data = conversations;
2188
+ this.conversationListCache.timestamp = Date.now();
2147
2189
  return conversations;
2148
2190
  } catch (error) {
2149
2191
  console.error('Failed to load conversations:', error);
@@ -2289,9 +2331,7 @@ class AgentGUIClient {
2289
2331
  if (this.ui.messageInput) {
2290
2332
  this.ui.messageInput.disabled = true;
2291
2333
  }
2292
- if (this.ui.sendButton) {
2293
- this.ui.sendButton.disabled = true;
2294
- }
2334
+ // Send button state managed by WebSocket connection, not streaming state
2295
2335
  const injectBtn = document.getElementById('injectBtn');
2296
2336
  const stopBtn = document.getElementById('stopBtn');
2297
2337
  if (injectBtn) injectBtn.disabled = true;
@@ -2305,9 +2345,7 @@ class AgentGUIClient {
2305
2345
  if (this.ui.messageInput) {
2306
2346
  this.ui.messageInput.disabled = false;
2307
2347
  }
2308
- if (this.ui.sendButton) {
2309
- this.ui.sendButton.disabled = false;
2310
- }
2348
+ // Send button state managed by WebSocket connection, not streaming state
2311
2349
  const injectBtn = document.getElementById('injectBtn');
2312
2350
  const stopBtn = document.getElementById('stopBtn');
2313
2351
  if (injectBtn) injectBtn.disabled = false;
@@ -2874,6 +2912,52 @@ class AgentGUIClient {
2874
2912
  };
2875
2913
  }
2876
2914
 
2915
+ /**
2916
+ * Save draft prompt for current conversation
2917
+ */
2918
+ saveDraftPrompt() {
2919
+ const convId = this.state.currentConversation?.id;
2920
+ if (convId && this.ui.messageInput) {
2921
+ const draft = this.ui.messageInput.value;
2922
+ this.draftPrompts.set(convId, draft);
2923
+ if (draft) {
2924
+ localStorage.setItem(`draft-${convId}`, draft);
2925
+ }
2926
+ }
2927
+ }
2928
+
2929
+ /**
2930
+ * Restore draft prompt for conversation
2931
+ */
2932
+ restoreDraftPrompt(conversationId) {
2933
+ if (!this.ui.messageInput) return;
2934
+
2935
+ let draft = this.draftPrompts.get(conversationId) || '';
2936
+ if (!draft) {
2937
+ draft = localStorage.getItem(`draft-${conversationId}`) || '';
2938
+ if (draft) this.draftPrompts.set(conversationId, draft);
2939
+ }
2940
+
2941
+ this.ui.messageInput.value = draft;
2942
+ }
2943
+
2944
+ /**
2945
+ * Clear draft for conversation
2946
+ */
2947
+ clearDraft(conversationId) {
2948
+ this.draftPrompts.delete(conversationId);
2949
+ localStorage.removeItem(`draft-${conversationId}`);
2950
+ }
2951
+
2952
+ /**
2953
+ * Update send button state based on WebSocket connection
2954
+ */
2955
+ updateSendButtonState() {
2956
+ if (this.ui.sendButton) {
2957
+ this.ui.sendButton.disabled = !this.wsManager.isConnected;
2958
+ }
2959
+ }
2960
+
2877
2961
  /**
2878
2962
  * Cleanup resources
2879
2963
  */