agentgui 1.0.257 → 1.0.258

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.257",
3
+ "version": "1.0.258",
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
@@ -38,18 +38,6 @@
38
38
  --sidebar-width: 300px;
39
39
  --header-height: 52px;
40
40
  --msg-max-width: 100%;
41
- --block-color-0: #8b5cf6;
42
- --block-color-1: #ec4899;
43
- --block-color-2: #14b8a6;
44
- --block-color-3: #f97316;
45
- --block-color-4: #06b6d4;
46
- --block-color-5: #84cc16;
47
- --block-color-6: #a855f7;
48
- --block-color-7: #f43f5e;
49
- --block-color-8: #22c55e;
50
- --block-color-9: #eab308;
51
- --block-color-10: #0ea5e9;
52
- --block-color-11: #d946ef;
53
41
  }
54
42
 
55
43
  html.dark {
@@ -58,18 +46,6 @@
58
46
  --color-text-primary: #f9fafb;
59
47
  --color-text-secondary: #d1d5db;
60
48
  --color-border: #374151;
61
- --block-color-0: #a78bfa;
62
- --block-color-1: #f472b6;
63
- --block-color-2: #2dd4bf;
64
- --block-color-3: #fb923c;
65
- --block-color-4: #22d3ee;
66
- --block-color-5: #a3e635;
67
- --block-color-6: #c084fc;
68
- --block-color-7: #fb7185;
69
- --block-color-8: #4ade80;
70
- --block-color-9: #facc15;
71
- --block-color-10: #38bdf8;
72
- --block-color-11: #e879f9;
73
49
  }
74
50
 
75
51
  html, body {
@@ -1874,6 +1850,163 @@
1874
1850
  .folded-tool-info > .folded-tool-body { border-top-color: #c7d2fe; }
1875
1851
  html.dark .folded-tool-info > .folded-tool-body { border-top-color: #3730a3; }
1876
1852
 
1853
+ /* --- Per-block-type unique colored backgrounds --- */
1854
+ .block-type-text { background: #f8fafc; }
1855
+ html.dark .block-type-text { background: #1e293b; }
1856
+
1857
+ .block-type-tool_use { background: #ecfeff; }
1858
+ html.dark .block-type-tool_use { background: #0c1a24; }
1859
+ .block-type-tool_use.folded-tool > .folded-tool-bar { background: #cffafe; }
1860
+ html.dark .block-type-tool_use.folded-tool > .folded-tool-bar { background: #0e2a3a; }
1861
+ .block-type-tool_use.folded-tool > .folded-tool-bar:hover { background: #a5f3fc; }
1862
+ html.dark .block-type-tool_use.folded-tool > .folded-tool-bar:hover { background: #164e63; }
1863
+ .block-type-tool_use.folded-tool > .folded-tool-bar::before { color: #0891b2; }
1864
+ html.dark .block-type-tool_use.folded-tool > .folded-tool-bar::before { color: #22d3ee; }
1865
+ .block-type-tool_use .folded-tool-icon { color: #0891b2; }
1866
+ html.dark .block-type-tool_use .folded-tool-icon { color: #22d3ee; }
1867
+ .block-type-tool_use .folded-tool-name { color: #155e75; }
1868
+ html.dark .block-type-tool_use .folded-tool-name { color: #67e8f9; }
1869
+ .block-type-tool_use .folded-tool-desc { color: #0e7490; }
1870
+ html.dark .block-type-tool_use .folded-tool-desc { color: #22d3ee; }
1871
+ .block-type-tool_use > .folded-tool-body { border-top-color: #a5f3fc; }
1872
+ html.dark .block-type-tool_use > .folded-tool-body { border-top-color: #164e63; }
1873
+
1874
+ .block-type-tool_result { background: #f0fdf4; }
1875
+ html.dark .block-type-tool_result { background: #0a1f0f; }
1876
+ .block-type-tool_result .tool-result-status { background: #dcfce7; }
1877
+ html.dark .block-type-tool_result .tool-result-status { background: #0f2b1a; }
1878
+ .block-type-tool_result .folded-tool-icon { color: #16a34a; }
1879
+ html.dark .block-type-tool_result .folded-tool-icon { color: #4ade80; }
1880
+ .block-type-tool_result .folded-tool-name { color: #166534; }
1881
+ html.dark .block-type-tool_result .folded-tool-name { color: #86efac; }
1882
+ .block-type-tool_result > .folded-tool-body { border-top-color: #bbf7d0; }
1883
+ html.dark .block-type-tool_result > .folded-tool-body { border-top-color: #166534; }
1884
+ .block-type-tool_result.tool-result-error { background: #fef2f2; }
1885
+ html.dark .block-type-tool_result.tool-result-error { background: #1c0f0f; }
1886
+ .block-type-tool_result.tool-result-error .tool-result-status { background: #fee2e2; }
1887
+ html.dark .block-type-tool_result.tool-result-error .tool-result-status { background: #2c1010; }
1888
+ .block-type-tool_result.tool-result-error .folded-tool-icon { color: #dc2626; }
1889
+ html.dark .block-type-tool_result.tool-result-error .folded-tool-icon { color: #f87171; }
1890
+ .block-type-tool_result.tool-result-error .folded-tool-name { color: #991b1b; }
1891
+ html.dark .block-type-tool_result.tool-result-error .folded-tool-name { color: #fca5a5; }
1892
+
1893
+ .block-type-code { background: #1e293b; }
1894
+ html.dark .block-type-code { background: #0f172a; }
1895
+
1896
+ .block-type-thinking { background: #f5f3ff; }
1897
+ html.dark .block-type-thinking { background: #1e1033; }
1898
+
1899
+ .block-type-bash { background: #fffbeb; }
1900
+ html.dark .block-type-bash { background: #1c1507; }
1901
+
1902
+ .block-type-system { background: #eef2ff; }
1903
+ html.dark .block-type-system { background: #15103a; }
1904
+ .block-type-system.folded-tool > .folded-tool-bar { background: #e0e7ff; }
1905
+ html.dark .block-type-system.folded-tool > .folded-tool-bar { background: #1e1b4b; }
1906
+ .block-type-system.folded-tool > .folded-tool-bar:hover { background: #c7d2fe; }
1907
+ html.dark .block-type-system.folded-tool > .folded-tool-bar:hover { background: #312e81; }
1908
+ .block-type-system.folded-tool > .folded-tool-bar::before { color: #6366f1; }
1909
+ html.dark .block-type-system.folded-tool > .folded-tool-bar::before { color: #a5b4fc; }
1910
+ .block-type-system .folded-tool-icon { color: #6366f1; }
1911
+ html.dark .block-type-system .folded-tool-icon { color: #a5b4fc; }
1912
+ .block-type-system .folded-tool-name { color: #3730a3; }
1913
+ html.dark .block-type-system .folded-tool-name { color: #c7d2fe; }
1914
+ .block-type-system .folded-tool-desc { color: #4f46e5; }
1915
+ html.dark .block-type-system .folded-tool-desc { color: #a5b4fc; }
1916
+ .block-type-system > .folded-tool-body { border-top-color: #c7d2fe; }
1917
+ html.dark .block-type-system > .folded-tool-body { border-top-color: #3730a3; }
1918
+
1919
+ .block-type-result { background: #f0fdf4; }
1920
+ html.dark .block-type-result { background: #0a1f0f; }
1921
+ .block-type-result.folded-tool > .folded-tool-bar { background: #dcfce7; }
1922
+ html.dark .block-type-result.folded-tool > .folded-tool-bar { background: #0f2b1a; }
1923
+ .block-type-result.folded-tool > .folded-tool-bar:hover { background: #bbf7d0; }
1924
+ html.dark .block-type-result.folded-tool > .folded-tool-bar:hover { background: #14532d; }
1925
+ .block-type-result.folded-tool > .folded-tool-bar::before { color: #16a34a; }
1926
+ html.dark .block-type-result.folded-tool > .folded-tool-bar::before { color: #4ade80; }
1927
+ .block-type-result .folded-tool-icon { color: #16a34a; }
1928
+ html.dark .block-type-result .folded-tool-icon { color: #4ade80; }
1929
+ .block-type-result .folded-tool-name { color: #166534; }
1930
+ html.dark .block-type-result .folded-tool-name { color: #86efac; }
1931
+ .block-type-result .folded-tool-desc { color: #15803d; }
1932
+ html.dark .block-type-result .folded-tool-desc { color: #4ade80; }
1933
+ .block-type-result > .folded-tool-body { border-top-color: #bbf7d0; }
1934
+ html.dark .block-type-result > .folded-tool-body { border-top-color: #166534; }
1935
+
1936
+ .block-type-error { background: #fef2f2; }
1937
+ html.dark .block-type-error { background: #1c0f0f; }
1938
+ .block-type-error.folded-tool > .folded-tool-bar { background: #fee2e2; }
1939
+ html.dark .block-type-error.folded-tool > .folded-tool-bar { background: #2c1010; }
1940
+ .block-type-error.folded-tool > .folded-tool-bar:hover { background: #fecaca; }
1941
+ html.dark .block-type-error.folded-tool > .folded-tool-bar:hover { background: #451a1a; }
1942
+ .block-type-error.folded-tool > .folded-tool-bar::before { color: #ef4444; }
1943
+ html.dark .block-type-error.folded-tool > .folded-tool-bar::before { color: #f87171; }
1944
+ .block-type-error .folded-tool-icon { color: #ef4444; }
1945
+ html.dark .block-type-error .folded-tool-icon { color: #f87171; }
1946
+ .block-type-error .folded-tool-name { color: #991b1b; }
1947
+ html.dark .block-type-error .folded-tool-name { color: #fca5a5; }
1948
+ .block-type-error .folded-tool-desc { color: #b91c1c; }
1949
+ html.dark .block-type-error .folded-tool-desc { color: #f87171; }
1950
+ .block-type-error > .folded-tool-body { border-top-color: #fecaca; }
1951
+ html.dark .block-type-error > .folded-tool-body { border-top-color: #7f1d1d; }
1952
+
1953
+ .block-type-image { background: #fdf2f8; }
1954
+ html.dark .block-type-image { background: #1f0a1a; }
1955
+
1956
+ .block-type-plan { background: #eff6ff; }
1957
+ html.dark .block-type-plan { background: #0c1929; }
1958
+
1959
+ .block-type-usage { background: #f9fafb; }
1960
+ html.dark .block-type-usage { background: #1f2937; }
1961
+
1962
+ .block-type-premature { background: #fffbeb; }
1963
+ html.dark .block-type-premature { background: #1c1507; }
1964
+
1965
+ .block-type-tool_status { background: #f0f9ff; }
1966
+ html.dark .block-type-tool_status { background: #0c1929; }
1967
+
1968
+ .block-type-generic { background: #f9fafb; }
1969
+ html.dark .block-type-generic { background: #1f2937; }
1970
+
1971
+ /* --- Code block header (non-collapsible) --- */
1972
+ .code-block-header {
1973
+ display: flex;
1974
+ align-items: center;
1975
+ gap: 0.5rem;
1976
+ padding: 0.3rem 0.75rem;
1977
+ background: #1f2937;
1978
+ color: #9ca3af;
1979
+ font-family: 'Monaco','Menlo','Ubuntu Mono', monospace;
1980
+ font-size: 0.75rem;
1981
+ }
1982
+ .code-block-header .copy-code-btn {
1983
+ margin-left: auto;
1984
+ background: none;
1985
+ border: none;
1986
+ color: #6b7280;
1987
+ cursor: pointer;
1988
+ padding: 0.125rem;
1989
+ border-radius: 0.25rem;
1990
+ display: flex;
1991
+ align-items: center;
1992
+ transition: all 0.15s;
1993
+ }
1994
+ .code-block-header .copy-code-btn:hover { color: #e5e7eb; background: #4b5563; }
1995
+ .code-block-header .copy-code-btn svg { width: 0.875rem; height: 0.875rem; }
1996
+
1997
+ /* --- Tool result success styling in body --- */
1998
+ .tool-result-success .tool-result-status {
1999
+ background: #dcfce7;
2000
+ padding: 0.4rem 0.75rem;
2001
+ }
2002
+ html.dark .tool-result-success .tool-result-status {
2003
+ background: #0f2b1a;
2004
+ }
2005
+ .tool-result-success .folded-tool-icon { color: #16a34a; }
2006
+ html.dark .tool-result-success .folded-tool-icon { color: #4ade80; }
2007
+ .tool-result-success .folded-tool-name { color: #166534; font-weight: 600; }
2008
+ html.dark .tool-result-success .folded-tool-name { color: #86efac; }
2009
+
1877
2010
  /* --- Consecutive block joining --- */
1878
2011
  .folded-tool + .folded-tool,
1879
2012
  .block-tool-use + .block-tool-use {
@@ -1185,8 +1185,8 @@ class AgentGUIClient {
1185
1185
  const dName = hasRenderer ? StreamingRenderer.getToolDisplayName(tn) : tn;
1186
1186
  const tTitle = hasRenderer && block.input ? StreamingRenderer.getToolTitle(tn, block.input) : '';
1187
1187
  const iconHtml = hasRenderer && this.renderer ? `<span class="folded-tool-icon">${this.renderer.getToolIcon(tn)}</span>` : '';
1188
- const colorIdx = hasRenderer && this.renderer ? this.renderer._getBlockColorIndex('tool_use') : 1;
1189
- html += `<details class="block-tool-use folded-tool" style="border-left:3px solid var(--block-color-${colorIdx})"><summary class="folded-tool-bar">${iconHtml}<span class="folded-tool-name">${this.escapeHtml(dName)}</span>${tTitle ? `<span class="folded-tool-desc">${this.escapeHtml(tTitle)}</span>` : ''}</summary>${inputHtml}`;
1188
+ const typeClass = hasRenderer && this.renderer ? this.renderer._getBlockTypeClass('tool_use') : 'block-type-tool_use';
1189
+ html += `<details class="block-tool-use folded-tool ${typeClass}"><summary class="folded-tool-bar">${iconHtml}<span class="folded-tool-name">${this.escapeHtml(dName)}</span>${tTitle ? `<span class="folded-tool-desc">${this.escapeHtml(tTitle)}</span>` : ''}</summary>${inputHtml}`;
1190
1190
  pendingToolUseClose = true;
1191
1191
  } else if (block.type === 'tool_result') {
1192
1192
  const content = typeof block.content === 'string' ? block.content : JSON.stringify(block.content);
@@ -1195,8 +1195,8 @@ class AgentGUIClient {
1195
1195
  const resultIcon = block.is_error
1196
1196
  ? '<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/></svg>'
1197
1197
  : '<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>';
1198
- const colorIdx = hasRenderer && this.renderer ? this.renderer._getBlockColorIndex('tool_result') : 2;
1199
- const resultHtml = `<div class="tool-result-inline${block.is_error ? ' tool-result-error' : ''}" style="border-left:3px solid var(--block-color-${colorIdx})"><div class="tool-result-status"><span class="folded-tool-icon">${resultIcon}</span><span class="folded-tool-name">${block.is_error ? 'Error' : 'Success'}</span><span class="folded-tool-desc">${this.escapeHtml(resultPreview)}</span></div><div class="folded-tool-body">${smartHtml}</div></div>`;
1198
+ const resultTypeClass = hasRenderer && this.renderer ? this.renderer._getBlockTypeClass('tool_result') : 'block-type-tool_result';
1199
+ const resultHtml = `<div class="tool-result-inline${block.is_error ? ' tool-result-error' : ' tool-result-success'} ${resultTypeClass}"><div class="tool-result-status"><span class="folded-tool-icon">${resultIcon}</span><span class="folded-tool-name">${block.is_error ? 'Error' : 'Success'}</span></div><div class="folded-tool-body">${smartHtml}</div></div>`;
1200
1200
  if (pendingToolUseClose) {
1201
1201
  html += resultHtml + '</details>';
1202
1202
  pendingToolUseClose = false;
@@ -1865,6 +1865,9 @@ class AgentGUIClient {
1865
1865
  } else if (status.modelsDownloading) {
1866
1866
  this._modelDownloadProgress = status.modelsProgress || { downloading: true };
1867
1867
  this._modelDownloadInProgress = true;
1868
+ setTimeout(function() {
1869
+ if (window.__showVoiceDownloadProgress) window.__showVoiceDownloadProgress();
1870
+ }, 0);
1868
1871
  } else {
1869
1872
  this._modelDownloadProgress = { done: false };
1870
1873
  this._modelDownloadInProgress = false;
@@ -2059,7 +2062,11 @@ class AgentGUIClient {
2059
2062
  if (progress.started || progress.downloading) {
2060
2063
  this._modelDownloadInProgress = true;
2061
2064
  this._updateConnectionIndicator(this.wsManager?.latency?.quality || 'unknown');
2062
-
2065
+
2066
+ if (!window._voiceProgressDialog && window.__showVoiceDownloadProgress) {
2067
+ window.__showVoiceDownloadProgress();
2068
+ }
2069
+
2063
2070
  if (window._voiceProgressDialog && progress.totalBytes > 0) {
2064
2071
  var pct = Math.round((progress.totalDownloaded / progress.totalBytes) * 100);
2065
2072
  var mb = Math.round(progress.totalBytes / 1024 / 1024);
@@ -335,6 +335,7 @@
335
335
  }
336
336
 
337
337
  window.__checkVoiceReady = isVoiceReady;
338
+ window.__showVoiceDownloadProgress = showVoiceDownloadProgress;
338
339
 
339
340
  function switchView(view) {
340
341
  currentView = view;
@@ -413,30 +413,13 @@ class StreamingRenderer {
413
413
  div.className = 'block-text';
414
414
  if (isHtml) div.classList.add('html-content');
415
415
  div.innerHTML = html;
416
- const colorIndex = this._getBlockColorIndex('text');
417
- div.style.borderLeft = `3px solid var(--block-color-${colorIndex})`;
416
+ div.classList.add(this._getBlockTypeClass('text'));
418
417
  return div;
419
418
  }
420
419
 
421
- _getBlockColorIndex(blockType) {
422
- const typeColors = {
423
- 'text': 0,
424
- 'tool_use': 1,
425
- 'tool_result': 2,
426
- 'code': 3,
427
- 'thinking': 4,
428
- 'bash': 5,
429
- 'system': 6,
430
- 'result': 7,
431
- 'error': 8,
432
- 'image': 9,
433
- 'plan': 10,
434
- 'usage': 11,
435
- 'premature': 8,
436
- 'tool_status': 7,
437
- 'generic': 0
438
- };
439
- return typeColors[blockType] !== undefined ? typeColors[blockType] : 0;
420
+ _getBlockTypeClass(blockType) {
421
+ const validTypes = ['text','tool_use','tool_result','code','thinking','bash','system','result','error','image','plan','usage','premature','tool_status','generic'];
422
+ return validTypes.includes(blockType) ? `block-type-${blockType}` : 'block-type-generic';
440
423
  }
441
424
 
442
425
  containsHtmlTags(text) {
@@ -484,25 +467,22 @@ class StreamingRenderer {
484
467
  renderBlockCode(block, context) {
485
468
  const div = document.createElement('div');
486
469
  div.className = 'block-code';
487
- div.style.borderLeft = `3px solid var(--block-color-${this._getBlockColorIndex('code')})`;
470
+ div.classList.add(this._getBlockTypeClass('code'));
488
471
 
489
472
  const code = block.code || '';
490
473
  const language = (block.language || 'plaintext').toLowerCase();
491
474
  const lineCount = code.split('\n').length;
492
475
 
493
- const details = document.createElement('details');
494
- details.className = 'collapsible-code';
495
-
496
- const summary = document.createElement('summary');
497
- summary.className = 'collapsible-code-summary';
498
- summary.innerHTML = `
476
+ const header = document.createElement('div');
477
+ header.className = 'code-block-header';
478
+ header.innerHTML = `
499
479
  <span class="collapsible-code-label">${this.escapeHtml(language)} - ${lineCount} line${lineCount !== 1 ? 's' : ''}</span>
500
480
  <button class="copy-code-btn" title="Copy code">
501
481
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
502
482
  </button>
503
483
  `;
504
484
 
505
- const copyBtn = summary.querySelector('.copy-code-btn');
485
+ const copyBtn = header.querySelector('.copy-code-btn');
506
486
  copyBtn.addEventListener('click', (e) => {
507
487
  e.preventDefault();
508
488
  e.stopPropagation();
@@ -517,9 +497,8 @@ class StreamingRenderer {
517
497
  const codeContainer = document.createElement('div');
518
498
  codeContainer.innerHTML = `<pre style="${preStyle}"><code class="lazy-hl">${this.escapeHtml(code)}</code></pre>`;
519
499
 
520
- details.appendChild(summary);
521
- details.appendChild(codeContainer);
522
- div.appendChild(details);
500
+ div.appendChild(header);
501
+ div.appendChild(codeContainer);
523
502
 
524
503
  return div;
525
504
  }
@@ -530,8 +509,7 @@ class StreamingRenderer {
530
509
  renderBlockThinking(block, context) {
531
510
  const div = document.createElement('div');
532
511
  div.className = 'block-thinking';
533
- const colorIndex = this._getBlockColorIndex('thinking');
534
- div.style.borderLeft = `3px solid var(--block-color-${colorIndex})`;
512
+ div.classList.add(this._getBlockTypeClass('thinking'));
535
513
 
536
514
  const thinking = block.thinking || '';
537
515
  div.innerHTML = `
@@ -662,7 +640,7 @@ class StreamingRenderer {
662
640
  const truncated = lineCount > 50;
663
641
  const displayCode = truncated ? codeLines.slice(0, 50).join('\n') : input.code;
664
642
  const lang = input.runtime || 'javascript';
665
- html += `<div style="margin-top:0.5rem"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:0.25rem"><span style="font-size:0.7rem;font-weight:600;color:#0891b2;text-transform:uppercase">${this.escapeHtml(lang)}</span><span style="font-size:0.7rem;color:var(--color-text-secondary)">${lineCount} lines</span></div>${StreamingRenderer.renderCodeWithHighlight(displayCode, this.escapeHtml.bind(this))}${truncated ? `<div style="font-size:0.7rem;color:var(--color-text-secondary);text-align:center;padding:0.25rem">... ${lineCount - 50} more lines</div>` : ''}</div>`;
643
+ html += `<div style="margin-top:0.5rem"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:0.25rem"><span style="font-size:0.7rem;font-weight:600;color:#0891b2;text-transform:uppercase">${this.escapeHtml(lang)}</span><span style="font-size:0.7rem;color:var(--color-text-secondary)">${lineCount} lines</span></div>${StreamingRenderer.renderCodeWithHighlight(displayCode, this.escapeHtml.bind(this), true)}${truncated ? `<div style="font-size:0.7rem;color:var(--color-text-secondary);text-align:center;padding:0.25rem">... ${lineCount - 50} more lines</div>` : ''}</div>`;
666
644
  }
667
645
 
668
646
  // Render commands (bash commands)
@@ -691,7 +669,7 @@ class StreamingRenderer {
691
669
  const displayContent = truncated ? content.substring(0, maxLen) : content;
692
670
  const lineCount = content.split('\n').length;
693
671
  const codeBody = StreamingRenderer.detectCodeContent(displayContent)
694
- ? StreamingRenderer.renderCodeWithHighlight(displayContent, this.escapeHtml.bind(this))
672
+ ? StreamingRenderer.renderCodeWithHighlight(displayContent, this.escapeHtml.bind(this), true)
695
673
  : `<div class="preview-body">${this.escapeHtml(displayContent)}</div>`;
696
674
  return `<div class="tool-param-content-preview" style="margin-top:0.5rem"><div class="preview-header"><span>${this.escapeHtml(label)}</span><span style="font-weight:400">${lineCount} lines${truncated ? ' (truncated)' : ''}</span></div>${codeBody}${truncated ? '<div class="preview-truncated">... ' + (content.length - maxLen) + ' more characters</div>' : ''}</div>`;
697
675
  }
@@ -758,8 +736,7 @@ class StreamingRenderer {
758
736
  const details = document.createElement('details');
759
737
  details.className = 'block-tool-use folded-tool';
760
738
  if (block.id) details.dataset.toolUseId = block.id;
761
- const colorIndex = this._getBlockColorIndex('tool_use');
762
- details.style.borderLeft = `3px solid var(--block-color-${colorIndex})`;
739
+ details.classList.add(this._getBlockTypeClass('tool_use'));
763
740
  const summary = document.createElement('summary');
764
741
  summary.className = 'folded-tool-bar';
765
742
  const displayName = this.getToolUseDisplayName(toolName);
@@ -831,7 +808,7 @@ class StreamingRenderer {
831
808
  if (data.length > 200 && StreamingRenderer.detectCodeContent(data)) {
832
809
  const displayData = data.length > 1000 ? data.substring(0, 1000) : data;
833
810
  const suffix = data.length > 1000 ? `<div style="font-size:0.7rem;color:var(--color-text-secondary);text-align:center;padding:0.25rem">... ${data.length - 1000} more characters</div>` : '';
834
- return `<div style="max-height:200px;overflow-y:auto">${StreamingRenderer.renderCodeWithHighlight(displayData, this.escapeHtml.bind(this))}${suffix}</div>`;
811
+ return `<div style="max-height:200px;overflow-y:auto">${StreamingRenderer.renderCodeWithHighlight(displayData, this.escapeHtml.bind(this), true)}${suffix}</div>`;
835
812
  }
836
813
  if (data.length > 500) {
837
814
  const lines = data.split('\n').length;
@@ -1185,7 +1162,7 @@ class StreamingRenderer {
1185
1162
  if (data.length > 200 && StreamingRenderer.detectCodeContent(data)) {
1186
1163
  const displayData = data.length > 1000 ? data.substring(0, 1000) : data;
1187
1164
  const suffix = data.length > 1000 ? `<div style="font-size:0.7rem;color:var(--color-text-secondary);text-align:center;padding:0.25rem">... ${data.length - 1000} more characters</div>` : '';
1188
- return `<div style="max-height:200px;overflow-y:auto">${StreamingRenderer.renderCodeWithHighlight(displayData, esc)}${suffix}</div>`;
1165
+ return `<div style="max-height:200px;overflow-y:auto">${StreamingRenderer.renderCodeWithHighlight(displayData, esc, true)}${suffix}</div>`;
1189
1166
  }
1190
1167
  if (data.length > 500) {
1191
1168
  return `<div style="font-family:'Monaco','Menlo','Ubuntu Mono',monospace;font-size:0.75rem;white-space:pre-wrap;word-break:break-all;max-height:200px;overflow-y:auto;background:var(--color-bg-code);color:#d1d5db;padding:0.5rem;border-radius:0.375rem;line-height:1.5">${esc(data.substring(0, 1000))}${data.length > 1000 ? '\n... (' + (data.length - 1000) + ' more chars)' : ''}</div>`;
@@ -1228,22 +1205,19 @@ class StreamingRenderer {
1228
1205
  const parentIsOpen = context.parentIsOpen !== undefined ? context.parentIsOpen : true;
1229
1206
 
1230
1207
  const wrapper = document.createElement('div');
1231
- wrapper.className = 'tool-result-inline' + (isError ? ' tool-result-error' : '');
1208
+ wrapper.className = 'tool-result-inline' + (isError ? ' tool-result-error' : ' tool-result-success');
1232
1209
  wrapper.dataset.eventType = 'tool_result';
1233
1210
  if (block.tool_use_id) wrapper.dataset.toolUseId = block.tool_use_id;
1234
- const colorIndex = this._getBlockColorIndex('tool_result');
1235
- wrapper.style.borderLeft = `3px solid var(--block-color-${colorIndex})`;
1211
+ wrapper.classList.add(this._getBlockTypeClass('tool_result'));
1236
1212
 
1237
1213
  const header = document.createElement('div');
1238
1214
  header.className = 'tool-result-status';
1239
1215
  const iconSvg = isError
1240
1216
  ? '<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/></svg>'
1241
1217
  : '<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>';
1242
- const preview = contentStr.length > 80 ? contentStr.substring(0, 77).replace(/\n/g, ' ') + '...' : contentStr.replace(/\n/g, ' ');
1243
1218
  header.innerHTML = `
1244
1219
  <span class="folded-tool-icon">${iconSvg}</span>
1245
1220
  <span class="folded-tool-name">${isError ? 'Error' : 'Success'}</span>
1246
- <span class="folded-tool-desc">${this.escapeHtml(preview)}</span>
1247
1221
  `;
1248
1222
  wrapper.appendChild(header);
1249
1223
 
@@ -1265,7 +1239,7 @@ class StreamingRenderer {
1265
1239
  renderBlockImage(block, context) {
1266
1240
  const div = document.createElement('div');
1267
1241
  div.className = 'block-image';
1268
- div.style.borderLeft = `3px solid var(--block-color-${this._getBlockColorIndex('image')})`;
1242
+ div.classList.add(this._getBlockTypeClass('image'));
1269
1243
 
1270
1244
  let src = block.image || block.src || '';
1271
1245
  const alt = block.alt || 'Image';
@@ -1289,8 +1263,7 @@ class StreamingRenderer {
1289
1263
  renderBlockBash(block, context) {
1290
1264
  const div = document.createElement('div');
1291
1265
  div.className = 'block-bash';
1292
- const colorIndex = this._getBlockColorIndex('bash');
1293
- div.style.borderLeft = `3px solid var(--block-color-${colorIndex})`;
1266
+ div.classList.add(this._getBlockTypeClass('bash'));
1294
1267
 
1295
1268
  const command = block.command || block.code || '';
1296
1269
  const output = block.output || '';
@@ -1301,7 +1274,7 @@ class StreamingRenderer {
1301
1274
  // For output, check if it looks like code and use syntax highlighting
1302
1275
  if (output) {
1303
1276
  if (StreamingRenderer.detectCodeContent(output)) {
1304
- html += StreamingRenderer.renderCodeWithHighlight(output, this.escapeHtml.bind(this));
1277
+ html += StreamingRenderer.renderCodeWithHighlight(output, this.escapeHtml.bind(this), true);
1305
1278
  } else {
1306
1279
  html += `<pre class="bash-output"><code>${this.escapeHtml(output)}</code></pre>`;
1307
1280
  }
@@ -1318,7 +1291,7 @@ class StreamingRenderer {
1318
1291
  const details = document.createElement('details');
1319
1292
  details.className = 'folded-tool folded-tool-info';
1320
1293
  details.dataset.eventType = 'system';
1321
- details.style.borderLeft = `3px solid var(--block-color-${this._getBlockColorIndex('system')})`;
1294
+ details.classList.add(this._getBlockTypeClass('system'));
1322
1295
  const desc = block.model ? this.escapeHtml(block.model) : 'Session';
1323
1296
  const summary = document.createElement('summary');
1324
1297
  summary.className = 'folded-tool-bar';
@@ -1355,8 +1328,7 @@ class StreamingRenderer {
1355
1328
  const details = document.createElement('details');
1356
1329
  details.className = isError ? 'folded-tool folded-tool-error' : 'folded-tool';
1357
1330
  details.dataset.eventType = 'result';
1358
- const colorIndex = this._getBlockColorIndex(isError ? 'error' : 'result');
1359
- details.style.borderLeft = `3px solid var(--block-color-${colorIndex})`;
1331
+ details.classList.add(this._getBlockTypeClass(isError ? 'error' : 'result'));
1360
1332
 
1361
1333
  const iconSvg = isError
1362
1334
  ? '<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/></svg>'
@@ -1411,7 +1383,7 @@ class StreamingRenderer {
1411
1383
  const div = document.createElement('div');
1412
1384
  div.className = 'block-tool-status';
1413
1385
  div.dataset.toolUseId = block.tool_use_id || '';
1414
- div.style.borderLeft = `3px solid var(--block-color-${this._getBlockColorIndex('tool_use')})`;
1386
+ div.classList.add(this._getBlockTypeClass('tool_status'));
1415
1387
  div.innerHTML = `
1416
1388
  <div style="display:flex;align-items:center;gap:0.5rem;padding:0.25rem 0.5rem;font-size:0.75rem;color:var(--color-text-secondary)">
1417
1389
  ${statusIcons[status] || statusIcons.pending}
@@ -1432,7 +1404,7 @@ class StreamingRenderer {
1432
1404
 
1433
1405
  const div = document.createElement('div');
1434
1406
  div.className = 'block-usage';
1435
- div.style.borderLeft = `3px solid var(--block-color-${this._getBlockColorIndex('usage')})`;
1407
+ div.classList.add(this._getBlockTypeClass('usage'));
1436
1408
  div.innerHTML = `
1437
1409
  <div style="display:flex;gap:1rem;padding:0.25rem 0.5rem;font-size:0.7rem;color:var(--color-text-secondary);background:var(--color-bg-secondary);border-radius:0.25rem">
1438
1410
  ${used ? `<span><strong>Used:</strong> ${used.toLocaleString()}</span>` : ''}
@@ -1463,7 +1435,7 @@ class StreamingRenderer {
1463
1435
 
1464
1436
  const div = document.createElement('div');
1465
1437
  div.className = 'block-plan';
1466
- div.style.borderLeft = `3px solid var(--block-color-${this._getBlockColorIndex('plan')})`;
1438
+ div.classList.add(this._getBlockTypeClass('plan'));
1467
1439
  div.innerHTML = `
1468
1440
  <details class="folded-tool folded-tool-info">
1469
1441
  <summary class="folded-tool-bar">
@@ -1489,7 +1461,7 @@ class StreamingRenderer {
1489
1461
  renderBlockPremature(block, context) {
1490
1462
  const div = document.createElement('div');
1491
1463
  div.className = 'folded-tool folded-tool-error block-premature';
1492
- div.style.borderLeft = `3px solid var(--block-color-${this._getBlockColorIndex('premature')})`;
1464
+ div.classList.add(this._getBlockTypeClass('premature'));
1493
1465
  const code = block.exitCode != null ? ` (exit ${block.exitCode})` : '';
1494
1466
  const stderrDisplay = block.stderrText ? `<div class="folded-tool-content" style="margin-top:8px;padding:8px;background:rgba(0,0,0,0.05);border-radius:4px;font-family:monospace;font-size:0.9em;white-space:pre-wrap;">${this.escapeHtml(block.stderrText)}</div>` : '';
1495
1467
  div.innerHTML = `
@@ -1509,8 +1481,7 @@ class StreamingRenderer {
1509
1481
  renderBlockGeneric(block, context) {
1510
1482
  const div = document.createElement('div');
1511
1483
  div.className = 'block-generic';
1512
- const colorIndex = this._getBlockColorIndex('generic');
1513
- div.style.borderLeft = `3px solid var(--block-color-${colorIndex})`;
1484
+ div.classList.add(this._getBlockTypeClass('generic'));
1514
1485
 
1515
1486
  // Show key-value pairs instead of raw JSON
1516
1487
  const fieldsHtml = Object.entries(block)
@@ -1542,8 +1513,7 @@ class StreamingRenderer {
1542
1513
  renderBlockError(block, error) {
1543
1514
  const div = document.createElement('div');
1544
1515
  div.className = 'block-error';
1545
- const colorIndex = this._getBlockColorIndex('error');
1546
- div.style.borderLeft = `3px solid var(--block-color-${colorIndex})`;
1516
+ div.classList.add(this._getBlockTypeClass('error'));
1547
1517
 
1548
1518
  div.innerHTML = `
1549
1519
  <div style="display:flex;align-items:flex-start;gap:0.625rem">
@@ -1596,7 +1566,7 @@ class StreamingRenderer {
1596
1566
 
1597
1567
  // Fallback: simple progress indicator
1598
1568
  const div = document.createElement('div');
1599
- div.className = 'event-streaming-progress mb-2 p-2 border-l-4 border-blue-500';
1569
+ div.className = 'event-streaming-progress mb-2 p-2';
1600
1570
  div.dataset.eventId = event.id || '';
1601
1571
  div.dataset.eventType = 'streaming_progress';
1602
1572
 
@@ -1710,7 +1680,7 @@ class StreamingRenderer {
1710
1680
  */
1711
1681
  renderGitStatus(event) {
1712
1682
  const div = document.createElement('div');
1713
- div.className = 'event-git-status card mb-3 p-4 border-l-4 border-orange-500';
1683
+ div.className = 'event-git-status card mb-3 p-4';
1714
1684
  div.dataset.eventId = event.id || '';
1715
1685
  div.dataset.eventType = 'git_status';
1716
1686
 
@@ -1935,7 +1905,7 @@ class StreamingRenderer {
1935
1905
  */
1936
1906
  renderThinking(event) {
1937
1907
  const div = document.createElement('div');
1938
- div.className = 'event-thinking mb-3 p-4 bg-purple-50 dark:bg-purple-900 rounded border-l-4 border-purple-500';
1908
+ div.className = 'event-thinking mb-3 p-4 bg-purple-50 dark:bg-purple-900 rounded';
1939
1909
  div.dataset.eventId = event.id || '';
1940
1910
  div.dataset.eventType = 'thinking_block';
1941
1911