agentgui 1.0.211 → 1.0.212

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/database.js CHANGED
@@ -1120,6 +1120,24 @@ export const queries = {
1120
1120
  });
1121
1121
  },
1122
1122
 
1123
+ getChunksSinceSeq(sessionId, sinceSeq) {
1124
+ const stmt = prep(
1125
+ `SELECT id, sessionId, conversationId, sequence, type, data, created_at
1126
+ FROM chunks WHERE sessionId = ? AND sequence > ? ORDER BY sequence ASC`
1127
+ );
1128
+ const rows = stmt.all(sessionId, sinceSeq);
1129
+ return rows.map(row => {
1130
+ try {
1131
+ return {
1132
+ ...row,
1133
+ data: typeof row.data === 'string' ? JSON.parse(row.data) : row.data
1134
+ };
1135
+ } catch (e) {
1136
+ return row;
1137
+ }
1138
+ });
1139
+ },
1140
+
1123
1141
  deleteSessionChunks(sessionId) {
1124
1142
  const stmt = prep('DELETE FROM chunks WHERE sessionId = ?');
1125
1143
  const result = stmt.run(sessionId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.211",
3
+ "version": "1.0.212",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -941,9 +941,15 @@ const server = http.createServer(async (req, res) => {
941
941
  if (!sess) { sendJSON(req, res, 404, { error: 'Session not found' }); return; }
942
942
 
943
943
  const url = new URL(req.url, 'http://localhost');
944
+ const sinceSeq = parseInt(url.searchParams.get('sinceSeq') || '-1');
944
945
  const since = parseInt(url.searchParams.get('since') || '0');
945
946
 
946
- const chunks = queries.getChunksSince(sessionId, since);
947
+ let chunks;
948
+ if (sinceSeq >= 0) {
949
+ chunks = queries.getChunksSinceSeq(sessionId, sinceSeq);
950
+ } else {
951
+ chunks = queries.getChunksSince(sessionId, since);
952
+ }
947
953
  sendJSON(req, res, 200, { ok: true, chunks });
948
954
  return;
949
955
  }
@@ -1711,6 +1717,7 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
1711
1717
  conversationId,
1712
1718
  block: systemBlock,
1713
1719
  blockIndex: allBlocks.length,
1720
+ seq: currentSequence,
1714
1721
  timestamp: Date.now()
1715
1722
  });
1716
1723
  } else if (parsed.type === 'assistant' && parsed.message?.content) {
@@ -1726,6 +1733,7 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
1726
1733
  conversationId,
1727
1734
  block,
1728
1735
  blockIndex: allBlocks.length - 1,
1736
+ seq: currentSequence,
1729
1737
  timestamp: Date.now()
1730
1738
  });
1731
1739
 
@@ -1752,6 +1760,7 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
1752
1760
  conversationId,
1753
1761
  block: toolResultBlock,
1754
1762
  blockIndex: allBlocks.length,
1763
+ seq: currentSequence,
1755
1764
  timestamp: Date.now()
1756
1765
  });
1757
1766
  }
@@ -1777,6 +1786,7 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
1777
1786
  block: resultBlock,
1778
1787
  blockIndex: allBlocks.length,
1779
1788
  isResult: true,
1789
+ seq: currentSequence,
1780
1790
  timestamp: Date.now()
1781
1791
  });
1782
1792
 
@@ -1827,6 +1837,7 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
1827
1837
  sessionId,
1828
1838
  conversationId,
1829
1839
  eventCount,
1840
+ seq: currentSequence,
1830
1841
  timestamp: Date.now()
1831
1842
  });
1832
1843
 
@@ -2066,9 +2077,13 @@ wss.on('connection', (ws, req) => {
2066
2077
  }));
2067
2078
  } else if (data.type === 'set_voice') {
2068
2079
  ws.ttsVoiceId = data.voiceId || 'default';
2080
+ } else if (data.type === 'latency_report') {
2081
+ ws.latencyTier = data.quality || 'good';
2082
+ ws.latencyAvg = data.avg || 0;
2069
2083
  } else if (data.type === 'ping') {
2070
2084
  ws.send(JSON.stringify({
2071
2085
  type: 'pong',
2086
+ requestId: data.requestId,
2072
2087
  timestamp: Date.now()
2073
2088
  }));
2074
2089
  }
@@ -2097,13 +2112,16 @@ wss.on('connection', (ws, req) => {
2097
2112
  const BROADCAST_TYPES = new Set([
2098
2113
  'message_created', 'conversation_created', 'conversation_updated',
2099
2114
  'conversations_updated', 'conversation_deleted', 'queue_status', 'queue_updated',
2100
- 'streaming_start', 'streaming_complete', 'streaming_error',
2101
2115
  'rate_limit_hit', 'rate_limit_clear',
2102
2116
  'script_started', 'script_stopped', 'script_output'
2103
2117
  ]);
2104
2118
 
2105
2119
  const wsBatchQueues = new Map();
2106
- const WS_BATCH_INTERVAL = 16;
2120
+ const BATCH_BY_TIER = { excellent: 16, good: 32, fair: 50, poor: 100, bad: 200 };
2121
+
2122
+ function getBatchInterval(ws) {
2123
+ return BATCH_BY_TIER[ws.latencyTier] || 32;
2124
+ }
2107
2125
 
2108
2126
  function flushWsBatch(ws) {
2109
2127
  const queue = wsBatchQueues.get(ws);
@@ -2124,7 +2142,7 @@ function sendToClient(ws, data) {
2124
2142
  if (!queue) { queue = { msgs: [], timer: null }; wsBatchQueues.set(ws, queue); }
2125
2143
  queue.msgs.push(data);
2126
2144
  if (!queue.timer) {
2127
- queue.timer = setTimeout(() => flushWsBatch(ws), WS_BATCH_INTERVAL);
2145
+ queue.timer = setTimeout(() => flushWsBatch(ws), getBatchInterval(ws));
2128
2146
  }
2129
2147
  }
2130
2148
 
package/static/index.html CHANGED
@@ -2213,6 +2213,85 @@
2213
2213
  }
2214
2214
 
2215
2215
  html.dark .event-streaming-complete { background: linear-gradient(135deg, #0a1f0f, #0f2b1a); }
2216
+
2217
+ @keyframes skeleton-pulse {
2218
+ 0%, 100% { opacity: 0.4; }
2219
+ 50% { opacity: 0.15; }
2220
+ }
2221
+ .skeleton-pulse { animation: skeleton-pulse 1.5s ease-in-out infinite; }
2222
+ .skeleton-loading { padding: 1rem; }
2223
+
2224
+ .message-sending { opacity: 0.6; transition: opacity 0.3s ease; }
2225
+ .message-send-failed { border-left: 3px solid var(--color-error); }
2226
+
2227
+ .connection-indicator {
2228
+ display: inline-flex;
2229
+ align-items: center;
2230
+ gap: 0.375rem;
2231
+ padding: 0.25rem 0.5rem;
2232
+ border-radius: 1rem;
2233
+ font-size: 0.75rem;
2234
+ cursor: pointer;
2235
+ transition: all 0.3s ease;
2236
+ }
2237
+ .connection-dot {
2238
+ width: 8px;
2239
+ height: 8px;
2240
+ border-radius: 50%;
2241
+ transition: background-color 0.5s ease;
2242
+ }
2243
+ .connection-dot.excellent { background: #10b981; }
2244
+ .connection-dot.good { background: #10b981; }
2245
+ .connection-dot.fair { background: #f59e0b; }
2246
+ .connection-dot.poor { background: #f97316; }
2247
+ .connection-dot.bad { background: #ef4444; }
2248
+ .connection-dot.unknown { background: #6b7280; }
2249
+ .connection-dot.disconnected { background: #ef4444; animation: pulse 1.5s ease-in-out infinite; }
2250
+ .connection-dot.reconnecting { background: #f59e0b; animation: pulse 1s ease-in-out infinite; }
2251
+
2252
+ .connection-tooltip {
2253
+ position: absolute;
2254
+ top: 100%;
2255
+ right: 0;
2256
+ margin-top: 0.5rem;
2257
+ padding: 0.75rem;
2258
+ background: var(--color-bg-secondary);
2259
+ border: 1px solid var(--color-border);
2260
+ border-radius: 0.5rem;
2261
+ font-size: 0.75rem;
2262
+ white-space: nowrap;
2263
+ z-index: 100;
2264
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
2265
+ }
2266
+
2267
+ .new-content-pill {
2268
+ position: sticky;
2269
+ bottom: 0.5rem;
2270
+ left: 50%;
2271
+ transform: translateX(-50%);
2272
+ padding: 0.375rem 1rem;
2273
+ background: var(--color-primary);
2274
+ color: white;
2275
+ border: none;
2276
+ border-radius: 1rem;
2277
+ font-size: 0.8rem;
2278
+ cursor: pointer;
2279
+ z-index: 50;
2280
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
2281
+ transition: opacity 0.2s ease;
2282
+ }
2283
+ .new-content-pill:hover { opacity: 0.9; }
2284
+
2285
+ @keyframes block-appear {
2286
+ from { opacity: 0; transform: translateY(6px); }
2287
+ to { opacity: 1; transform: translateY(0); }
2288
+ }
2289
+ .streaming-blocks > * {
2290
+ animation: block-appear 0.2s ease-out both;
2291
+ }
2292
+ .streaming-blocks > details.block-tool-use {
2293
+ transition: max-height 0.3s ease;
2294
+ }
2216
2295
  </style>
2217
2296
  </head>
2218
2297
  <body>