agentgui 1.0.150 → 1.0.151

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.150",
3
+ "version": "1.0.151",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/static/index.html CHANGED
@@ -7,10 +7,14 @@
7
7
  <title>AgentGUI</title>
8
8
  <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='20' fill='%233b82f6'/%3E%3Ctext x='50' y='68' font-size='50' font-family='sans-serif' font-weight='bold' fill='white' text-anchor='middle'%3EG%3C/text%3E%3C/svg%3E">
9
9
 
10
+ <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
11
+ <link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
10
12
  <link href="https://cdn.jsdelivr.net/npm/rippleui@1.12.1/dist/css/styles.css" rel="stylesheet">
11
- <link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-dark.css" rel="stylesheet">
12
- <link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/github-dark.min.css" rel="stylesheet">
13
- <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"></script>
13
+ <link rel="preload" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-dark.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
14
+ <noscript><link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-dark.css" rel="stylesheet"></noscript>
15
+ <link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/github-dark.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
16
+ <noscript><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/github-dark.min.css" rel="stylesheet"></noscript>
17
+ <script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"></script>
14
18
 
15
19
  <style>
16
20
  *, *::before, *::after { box-sizing: border-box; }
@@ -1158,6 +1162,19 @@
1158
1162
  font-size: 0.9rem;
1159
1163
  }
1160
1164
 
1165
+ .block-text + .block-text {
1166
+ margin-top: -0.75rem;
1167
+ padding-top: 0;
1168
+ border-top-left-radius: 0;
1169
+ border-top-right-radius: 0;
1170
+ }
1171
+
1172
+ .block-text:has(+ .block-text) {
1173
+ margin-bottom: 0;
1174
+ border-bottom-left-radius: 0;
1175
+ border-bottom-right-radius: 0;
1176
+ }
1177
+
1161
1178
  .block-code {
1162
1179
  margin-bottom: 0.75rem;
1163
1180
  border-radius: 0.5rem;
@@ -2060,16 +2077,16 @@
2060
2077
  </div>
2061
2078
  </div>
2062
2079
 
2063
- <script src="/gm/js/event-processor.js"></script>
2064
- <script src="/gm/js/streaming-renderer.js"></script>
2065
- <script src="/gm/js/websocket-manager.js"></script>
2066
- <script src="/gm/js/event-filter.js"></script>
2067
- <script src="/gm/js/syntax-highlighter.js"></script>
2068
- <script src="/gm/js/ui-components.js"></script>
2069
- <script src="/gm/js/conversations.js"></script>
2070
- <script src="/gm/js/client.js"></script>
2080
+ <script defer src="/gm/js/event-processor.js"></script>
2081
+ <script defer src="/gm/js/streaming-renderer.js"></script>
2082
+ <script defer src="/gm/js/websocket-manager.js"></script>
2083
+ <script defer src="/gm/js/event-filter.js"></script>
2084
+ <script defer src="/gm/js/syntax-highlighter.js"></script>
2085
+ <script defer src="/gm/js/ui-components.js"></script>
2086
+ <script defer src="/gm/js/conversations.js"></script>
2087
+ <script defer src="/gm/js/client.js"></script>
2071
2088
  <script type="module" src="/gm/js/voice.js"></script>
2072
- <script src="/gm/js/features.js"></script>
2089
+ <script defer src="/gm/js/features.js"></script>
2073
2090
 
2074
2091
  <script>
2075
2092
  const savedTheme = localStorage.getItem('theme') || 'light';
@@ -135,12 +135,17 @@ class StreamingRenderer {
135
135
  const lastTime = this.dedupMap.get(key);
136
136
  const now = Date.now();
137
137
 
138
- // Deduplicate within 100ms window
139
138
  if (lastTime && (now - lastTime) < 100) {
140
139
  return true;
141
140
  }
142
141
 
143
142
  this.dedupMap.set(key, now);
143
+ if (this.dedupMap.size > 5000) {
144
+ const cutoff = now - 1000;
145
+ for (const [k, t] of this.dedupMap) {
146
+ if (t < cutoff) this.dedupMap.delete(k);
147
+ }
148
+ }
144
149
  return false;
145
150
  }
146
151
 
@@ -358,17 +363,25 @@ class StreamingRenderer {
358
363
  * Render text block with semantic HTML
359
364
  */
360
365
  renderBlockText(block, context) {
361
- const div = document.createElement('div');
362
- div.className = 'block-text';
363
-
364
366
  const text = block.text || '';
365
- if (this.containsHtmlTags(text)) {
366
- div.innerHTML = this.sanitizeHtml(text);
367
- div.classList.add('html-content');
368
- } else {
369
- div.innerHTML = this.parseAndRenderMarkdown(text);
367
+ const isHtml = this.containsHtmlTags(text);
368
+ const cached = this.renderCache.get(text);
369
+ const html = cached || (isHtml ? this.sanitizeHtml(text) : this.parseAndRenderMarkdown(text));
370
+
371
+ if (!cached && this.renderCache.size < 2000) {
372
+ this.renderCache.set(text, html);
373
+ }
374
+
375
+ const lastChild = this.outputContainer && this.outputContainer.lastElementChild;
376
+ if (lastChild && lastChild.classList.contains('block-text') && !isHtml && !lastChild.classList.contains('html-content')) {
377
+ lastChild.innerHTML += html;
378
+ return null;
370
379
  }
371
380
 
381
+ const div = document.createElement('div');
382
+ div.className = 'block-text';
383
+ if (isHtml) div.classList.add('html-content');
384
+ div.innerHTML = html;
372
385
  return div;
373
386
  }
374
387
 
@@ -447,11 +460,9 @@ class StreamingRenderer {
447
460
 
448
461
  const preStyle = "background:#1e293b;padding:1rem;border-radius:0 0 0.375rem 0.375rem;overflow-x:auto;font-family:'Monaco','Menlo','Ubuntu Mono',monospace;font-size:0.875rem;line-height:1.6;color:#e2e8f0;border:1px solid #334155;border-top:none;margin:0";
449
462
  const codeContainer = document.createElement('div');
463
+ codeContainer.innerHTML = `<pre style="${preStyle}"><code>${this.escapeHtml(code)}</code></pre>`;
450
464
  if (typeof hljs !== 'undefined') {
451
- const result = hljs.highlightAuto(code);
452
- codeContainer.innerHTML = `<pre style="${preStyle}"><code class="hljs">${result.value}</code></pre>`;
453
- } else {
454
- codeContainer.innerHTML = `<pre style="${preStyle}"><code>${this.escapeHtml(code)}</code></pre>`;
465
+ this.lazyHighlight(codeContainer, code);
455
466
  }
456
467
 
457
468
  details.appendChild(summary);
@@ -1785,13 +1796,39 @@ class StreamingRenderer {
1785
1796
  * Auto-scroll to bottom of container
1786
1797
  */
1787
1798
  autoScroll() {
1788
- if (this.scrollContainer) {
1789
- try {
1790
- this.scrollContainer.scrollTop = this.scrollContainer.scrollHeight;
1791
- } catch (e) {
1792
- // Ignore scroll errors
1799
+ if (this._scrollRafPending) return;
1800
+ this._scrollRafPending = true;
1801
+ requestAnimationFrame(() => {
1802
+ this._scrollRafPending = false;
1803
+ if (this.scrollContainer) {
1804
+ try { this.scrollContainer.scrollTop = this.scrollContainer.scrollHeight; } catch (_) {}
1793
1805
  }
1806
+ });
1807
+ }
1808
+
1809
+ lazyHighlight(container, code) {
1810
+ if (!this._hlObserver) {
1811
+ this._hlObserver = new IntersectionObserver((entries) => {
1812
+ for (const entry of entries) {
1813
+ if (!entry.isIntersecting) continue;
1814
+ const el = entry.target;
1815
+ const raw = el._rawCode;
1816
+ if (!raw) continue;
1817
+ this._hlObserver.unobserve(el);
1818
+ try {
1819
+ const codeEl = el.querySelector('code');
1820
+ if (codeEl && typeof hljs !== 'undefined') {
1821
+ const result = hljs.highlightAuto(raw);
1822
+ codeEl.classList.add('hljs');
1823
+ codeEl.innerHTML = result.value;
1824
+ }
1825
+ } catch (_) {}
1826
+ delete el._rawCode;
1827
+ }
1828
+ }, { rootMargin: '200px' });
1794
1829
  }
1830
+ container._rawCode = code;
1831
+ this._hlObserver.observe(container);
1795
1832
  }
1796
1833
 
1797
1834
  updateVirtualScroll() {