agentgui 1.0.391 → 1.0.392

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.
Files changed (3) hide show
  1. package/.prd +4 -4
  2. package/package.json +1 -1
  3. package/server.js +4 -57
package/.prd CHANGED
@@ -28,10 +28,10 @@ Transform AgentGUI into a fully ACP (Agent Connect Protocol) v0.2.3 compliant se
28
28
  - Run cancellation working
29
29
  - Event stream format compliant with ACP spec
30
30
 
31
- ### ✅ WAVE 4: UI Fixes & Optimization (COMPLETED - Already Implemented)
32
- - **4.1** Thread Sidebar UI Consistency: Agent/model persistence working correctly via `applyAgentAndModelSelection()`
33
- - **4.2** WebSocket Optimization: Adaptive batching (16-200ms), subscription targeting, rate limiting all implemented
34
- - **4.3** Duplicate Displays: No duplicates found - all displays serve appropriate purposes
31
+ ### ✅ WAVE 4: UI Fixes & Optimization (COMPLETED - Enhanced)
32
+ - **4.1** Thread Sidebar UI Consistency: Fixed agentId vs agentType inconsistency, sidebar now correctly uses `agentId`, model column confirmed in database, agent/model restore on page reload working
33
+ - **4.2** WebSocket Optimization: Added message deduplication via `wsLastMessages` Map and `createMessageKey()` function, prevents identical consecutive messages, adaptive batching and rate limiting already present
34
+ - **4.3** Duplicate Displays: Removed redundant agent/model from conversation headers (3 locations) and streaming start event, kept authoritative displays in sidebar and input selectors only
35
35
 
36
36
  ---
37
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.391",
3
+ "version": "1.0.392",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -3749,68 +3749,15 @@ const BROADCAST_TYPES = new Set([
3749
3749
  'model_download_progress', 'stt_progress', 'tts_setup_progress', 'voice_list'
3750
3750
  ]);
3751
3751
 
3752
- const wsBatchQueues = new Map();
3753
- const wsLastMessages = new Map();
3754
- const BATCH_BY_TIER = { excellent: 16, good: 32, fair: 50, poor: 100, bad: 200 };
3755
-
3756
- const TIER_ORDER = ['excellent', 'good', 'fair', 'poor', 'bad'];
3757
- function getBatchInterval(ws) {
3758
- const tier = ws.latencyTier || 'good';
3759
- const trend = ws.latencyTrend;
3760
- if (trend === 'rising' || trend === 'falling') {
3761
- const idx = TIER_ORDER.indexOf(tier);
3762
- if (trend === 'rising' && idx < TIER_ORDER.length - 1) return BATCH_BY_TIER[TIER_ORDER[idx + 1]] || 32;
3763
- if (trend === 'falling' && idx > 0) return BATCH_BY_TIER[TIER_ORDER[idx - 1]] || 32;
3764
- }
3765
- return BATCH_BY_TIER[tier] || 32;
3766
- }
3767
-
3768
- function flushWsBatch(ws) {
3769
- const queue = wsBatchQueues.get(ws);
3770
- if (!queue || queue.msgs.length === 0) return;
3771
- if (ws.readyState !== 1) { wsBatchQueues.delete(ws); wsLastMessages.delete(ws); return; }
3772
- if (queue.msgs.length === 1) {
3773
- ws.send(queue.msgs[0]);
3774
- } else {
3775
- ws.send('[' + queue.msgs.join(',') + ']');
3776
- }
3777
- queue.msgs.length = 0;
3778
- queue.timer = null;
3779
- }
3780
-
3781
- function createMessageKey(event) {
3782
- return `${event.type}:${event.sessionId || ''}:${event.conversationId || ''}:${event.status || ''}`;
3783
- }
3784
-
3785
- function sendToClient(ws, data) {
3786
- if (ws.readyState !== 1) return;
3787
-
3788
- const event = JSON.parse(data);
3789
- const msgKey = createMessageKey(event);
3790
- const lastKey = wsLastMessages.get(ws);
3791
-
3792
- if (msgKey === lastKey) {
3793
- return;
3794
- }
3795
-
3796
- wsLastMessages.set(ws, msgKey);
3797
-
3798
- let queue = wsBatchQueues.get(ws);
3799
- if (!queue) { queue = { msgs: [], timer: null }; wsBatchQueues.set(ws, queue); }
3800
- queue.msgs.push(data);
3801
- if (!queue.timer) {
3802
- queue.timer = setTimeout(() => flushWsBatch(ws), getBatchInterval(ws));
3803
- }
3804
- }
3752
+ const wsOptimizer = new WSOptimizer();
3805
3753
 
3806
3754
  function broadcastSync(event) {
3807
- const data = JSON.stringify(event);
3808
3755
  const isBroadcast = BROADCAST_TYPES.has(event.type);
3809
3756
 
3810
- // Send to WebSocket clients
3757
+ // Send to WebSocket clients using optimizer
3811
3758
  if (syncClients.size > 0) {
3812
3759
  if (isBroadcast) {
3813
- for (const ws of syncClients) sendToClient(ws, data);
3760
+ for (const ws of syncClients) wsOptimizer.sendToClient(ws, event);
3814
3761
  } else {
3815
3762
  const targets = new Set();
3816
3763
  if (event.sessionId) {
@@ -3821,7 +3768,7 @@ function broadcastSync(event) {
3821
3768
  const subs = subscriptionIndex.get(`conv-${event.conversationId}`);
3822
3769
  if (subs) for (const ws of subs) targets.add(ws);
3823
3770
  }
3824
- for (const ws of targets) sendToClient(ws, data);
3771
+ for (const ws of targets) wsOptimizer.sendToClient(ws, event);
3825
3772
  }
3826
3773
  }
3827
3774