agentgui 1.0.545 → 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.545",
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
 
@@ -191,6 +203,21 @@ class AgentGUIClient {
191
203
  if (dot) dot.classList.remove('degrading');
192
204
  });
193
205
 
206
+ // Switch to idle view when selecting non-streaming conversation
207
+ window.addEventListener('conversation-selected', (e) => {
208
+ const convId = e.detail.conversationId;
209
+ // Save draft from previous conversation before switching
210
+ this.saveDraftPrompt();
211
+
212
+ const isStreaming = convId && this.state.streamingConversations.has(convId);
213
+ if (!isStreaming && window.switchView) {
214
+ window.switchView('chat');
215
+ }
216
+
217
+ // Restore draft for new conversation after a tick
218
+ setTimeout(() => this.restoreDraftPrompt(convId), 0);
219
+ });
220
+
194
221
  // Preserve controls state across tab switches
195
222
  window.addEventListener('view-switched', (e) => {
196
223
  const view = e.detail.view;
@@ -383,6 +410,19 @@ class AgentGUIClient {
383
410
  this.ui.agentSelector = document.querySelector('[data-agent-selector]');
384
411
  this.ui.modelSelector = document.querySelector('[data-model-selector]');
385
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
+
386
426
  if (this.ui.cliSelector) {
387
427
  this.ui.cliSelector.addEventListener('change', () => {
388
428
  if (!this._agentLocked) {
@@ -2131,10 +2171,21 @@ class AgentGUIClient {
2131
2171
  * Load conversations
2132
2172
  */
2133
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
+
2134
2182
  return this._dedupedFetch('loadConversations', async () => {
2135
2183
  try {
2136
2184
  const { conversations } = await window.wsClient.rpc('conv.ls');
2137
2185
  this.state.conversations = conversations;
2186
+ // Update cache
2187
+ this.conversationListCache.data = conversations;
2188
+ this.conversationListCache.timestamp = Date.now();
2138
2189
  return conversations;
2139
2190
  } catch (error) {
2140
2191
  console.error('Failed to load conversations:', error);
@@ -2280,9 +2331,7 @@ class AgentGUIClient {
2280
2331
  if (this.ui.messageInput) {
2281
2332
  this.ui.messageInput.disabled = true;
2282
2333
  }
2283
- if (this.ui.sendButton) {
2284
- this.ui.sendButton.disabled = true;
2285
- }
2334
+ // Send button state managed by WebSocket connection, not streaming state
2286
2335
  const injectBtn = document.getElementById('injectBtn');
2287
2336
  const stopBtn = document.getElementById('stopBtn');
2288
2337
  if (injectBtn) injectBtn.disabled = true;
@@ -2296,9 +2345,7 @@ class AgentGUIClient {
2296
2345
  if (this.ui.messageInput) {
2297
2346
  this.ui.messageInput.disabled = false;
2298
2347
  }
2299
- if (this.ui.sendButton) {
2300
- this.ui.sendButton.disabled = false;
2301
- }
2348
+ // Send button state managed by WebSocket connection, not streaming state
2302
2349
  const injectBtn = document.getElementById('injectBtn');
2303
2350
  const stopBtn = document.getElementById('stopBtn');
2304
2351
  if (injectBtn) injectBtn.disabled = false;
@@ -2865,6 +2912,52 @@ class AgentGUIClient {
2865
2912
  };
2866
2913
  }
2867
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
+
2868
2961
  /**
2869
2962
  * Cleanup resources
2870
2963
  */
@@ -179,6 +179,8 @@
179
179
  });
180
180
  }
181
181
 
182
+ window.switchView = switchView;
183
+
182
184
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
183
185
  else init();
184
186
  })();