agentgui 1.0.126 → 1.0.128
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 +1 -1
- package/static/js/streaming-renderer.js +81 -92
package/package.json
CHANGED
|
@@ -581,22 +581,14 @@ class StreamingRenderer {
|
|
|
581
581
|
case 'dev__execute':
|
|
582
582
|
case 'dev_execute':
|
|
583
583
|
case 'execute': {
|
|
584
|
-
// Handle mcp__plugin_gm_dev__execute and similar dev execution tools
|
|
585
584
|
let html = '<div class="tool-params">';
|
|
586
585
|
|
|
587
|
-
// Show working directory if present
|
|
588
586
|
if (input.workingDirectory) {
|
|
589
|
-
html += `<div style="margin-bottom:0.5rem;font-size:0.75rem;color:var(--color-text-secondary)">
|
|
590
|
-
<span style="opacity:0.7">📁</span> ${this.escapeHtml(input.workingDirectory)}
|
|
591
|
-
</div>`;
|
|
587
|
+
html += `<div style="margin-bottom:0.5rem;font-size:0.75rem;color:var(--color-text-secondary)"><span style="opacity:0.7">📁</span> ${this.escapeHtml(input.workingDirectory)}</div>`;
|
|
592
588
|
}
|
|
593
589
|
|
|
594
|
-
// Show timeout if present
|
|
595
590
|
if (input.timeout) {
|
|
596
|
-
|
|
597
|
-
html += `<div style="margin-bottom:0.5rem;font-size:0.75rem;color:var(--color-text-secondary)">
|
|
598
|
-
<span style="opacity:0.7">⏱️</span> Timeout: ${seconds}s
|
|
599
|
-
</div>`;
|
|
591
|
+
html += `<div style="margin-bottom:0.5rem;font-size:0.75rem;color:var(--color-text-secondary)"><span style="opacity:0.7">⏱️</span> Timeout: ${Math.round(input.timeout / 1000)}s</div>`;
|
|
600
592
|
}
|
|
601
593
|
|
|
602
594
|
// Render code with syntax highlighting
|
|
@@ -605,16 +597,16 @@ class StreamingRenderer {
|
|
|
605
597
|
const lineCount = codeLines.length;
|
|
606
598
|
const truncated = lineCount > 50;
|
|
607
599
|
const displayCode = truncated ? codeLines.slice(0, 50).join('\n') : input.code;
|
|
608
|
-
|
|
609
600
|
const lang = input.runtime || 'javascript';
|
|
610
|
-
html += `<div style="margin-top:0.5rem"
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
601
|
+
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>`;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Render commands (bash commands)
|
|
605
|
+
if (input.commands) {
|
|
606
|
+
const cmds = Array.isArray(input.commands) ? input.commands : [input.commands];
|
|
607
|
+
cmds.forEach(cmd => {
|
|
608
|
+
html += `<div style="margin-top:0.375rem"><div class="tool-param-command"><span class="prompt-char">$</span><span class="command-text">${this.escapeHtml(typeof cmd === 'string' ? cmd : JSON.stringify(cmd))}</span></div></div>`;
|
|
609
|
+
});
|
|
618
610
|
}
|
|
619
611
|
|
|
620
612
|
html += '</div>';
|
|
@@ -756,14 +748,23 @@ class StreamingRenderer {
|
|
|
756
748
|
return `<div style="padding:0.5rem"><img src="${esc(trimmed)}" style="max-width:100%;max-height:24rem;border-radius:0.375rem" loading="lazy"></div>`;
|
|
757
749
|
}
|
|
758
750
|
|
|
759
|
-
//
|
|
751
|
+
// Parse JSON and render as structured content
|
|
760
752
|
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
|
|
761
753
|
try {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
//
|
|
765
|
-
|
|
766
|
-
|
|
754
|
+
const parsed = JSON.parse(trimmed);
|
|
755
|
+
|
|
756
|
+
// Handle Claude content block arrays: [{type:"text", text:"..."}]
|
|
757
|
+
if (Array.isArray(parsed) && parsed.length > 0 && parsed[0] && parsed[0].type === 'text') {
|
|
758
|
+
const textParts = parsed.filter(b => b.type === 'text' && b.text);
|
|
759
|
+
if (textParts.length > 0) {
|
|
760
|
+
const combined = textParts.map(b => b.text).join('\n');
|
|
761
|
+
// Re-enter renderSmartContentHTML with the extracted text
|
|
762
|
+
return StreamingRenderer.renderSmartContentHTML(combined, esc);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// For other JSON, render as itemized key-value structure
|
|
767
|
+
return `<div style="padding:0.5rem 0.75rem">${StreamingRenderer.renderParamsHTML(parsed, 0, esc)}</div>`;
|
|
767
768
|
} catch (e) {
|
|
768
769
|
// Not valid JSON, might be code with braces
|
|
769
770
|
}
|
|
@@ -990,81 +991,64 @@ class StreamingRenderer {
|
|
|
990
991
|
* Render code with basic syntax highlighting
|
|
991
992
|
*/
|
|
992
993
|
static renderCodeWithHighlight(code, esc) {
|
|
993
|
-
//
|
|
994
|
-
|
|
994
|
+
// Tokenize-then-replace approach: collect spans as tokens so regexes
|
|
995
|
+
// never see previously-injected HTML, preventing cascading corruption.
|
|
996
|
+
const tokens = [];
|
|
997
|
+
const mkToken = (cls, text) => {
|
|
998
|
+
const id = `\x00T${tokens.length}\x00`;
|
|
999
|
+
tokens.push({ id, cls, text });
|
|
1000
|
+
return id;
|
|
1001
|
+
};
|
|
995
1002
|
|
|
996
|
-
|
|
1003
|
+
let src = code;
|
|
1004
|
+
|
|
1005
|
+
// Detect JSON
|
|
997
1006
|
const isJSON = (code.trim().startsWith('{') || code.trim().startsWith('[')) &&
|
|
998
1007
|
code.includes('"') && (code.includes(':') || code.includes(','));
|
|
999
1008
|
|
|
1000
1009
|
if (isJSON) {
|
|
1001
|
-
// JSON
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
// Booleans and null
|
|
1010
|
-
{ pattern: /:\s*(true|false|null)/g, replacement: ': <span style="color:#ef4444">$1</span>' },
|
|
1011
|
-
// Array/object brackets
|
|
1012
|
-
{ pattern: /([\[\]{}])/g, replacement: '<span style="color:#6b7280;font-weight:600">$1</span>' },
|
|
1013
|
-
];
|
|
1014
|
-
|
|
1015
|
-
jsonHighlights.forEach(({ pattern, replacement }) => {
|
|
1016
|
-
highlighted = highlighted.replace(pattern, replacement);
|
|
1017
|
-
});
|
|
1010
|
+
// JSON keys
|
|
1011
|
+
src = src.replace(/"([^"]+)"\s*:/g, (m, k) => `"${mkToken('jk', k)}":`);
|
|
1012
|
+
// JSON string values
|
|
1013
|
+
src = src.replace(/:\s*"([^"]*)"/g, (m, v) => `: "${mkToken('js', v)}"`);
|
|
1014
|
+
// JSON numbers
|
|
1015
|
+
src = src.replace(/:\s*(\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g, (m, n) => `: ${mkToken('jn', n)}`);
|
|
1016
|
+
// JSON booleans/null
|
|
1017
|
+
src = src.replace(/:\s*(true|false|null)/g, (m, b) => `: ${mkToken('jb', b)}`);
|
|
1018
1018
|
} else {
|
|
1019
|
-
//
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
replacement: '<span style="color:#8b5cf6;font-weight:600">$1</span>' },
|
|
1037
|
-
{ pattern: /\b(public|private|protected|static|final|abstract|interface|extends|implements|package|void|int|string|boolean|float|double|char)\b/g,
|
|
1038
|
-
replacement: '<span style="color:#8b5cf6;font-weight:600">$1</span>' },
|
|
1039
|
-
|
|
1040
|
-
// Type annotations
|
|
1041
|
-
{ pattern: /:\s*([A-Z][a-zA-Z0-9_]*)/g, replacement: ': <span style="color:#0891b2">$1</span>' },
|
|
1042
|
-
|
|
1043
|
-
// Numbers
|
|
1044
|
-
{ pattern: /\b(\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\b/g, replacement: '<span style="color:#f59e0b">$1</span>' },
|
|
1045
|
-
|
|
1046
|
-
// Booleans and null
|
|
1047
|
-
{ pattern: /\b(true|false|null|undefined|None|True|False|nil)\b/g, replacement: '<span style="color:#ef4444">$1</span>' },
|
|
1048
|
-
|
|
1049
|
-
// Function/method names (improved)
|
|
1050
|
-
{ pattern: /\b([a-zA-Z_][a-zA-Z0-9_]*)(?=\s*\()/g, replacement: '<span style="color:#3b82f6">$1</span>' },
|
|
1051
|
-
|
|
1052
|
-
// Operators
|
|
1053
|
-
{ pattern: /(===|!==|==|!=|<=|>=|&&|\|\||\+=|-=|\*=|\/=|%=|=>|->)/g, replacement: '<span style="color:#a855f7">$1</span>' },
|
|
1054
|
-
];
|
|
1055
|
-
|
|
1056
|
-
// Apply highlights
|
|
1057
|
-
highlights.forEach(({ pattern, replacement }) => {
|
|
1058
|
-
if (typeof replacement === 'function') {
|
|
1059
|
-
highlighted = highlighted.replace(pattern, replacement);
|
|
1060
|
-
} else {
|
|
1061
|
-
highlighted = highlighted.replace(pattern, replacement);
|
|
1062
|
-
}
|
|
1063
|
-
});
|
|
1019
|
+
// Comments
|
|
1020
|
+
src = src.replace(/(\/\/[^\n]*)/g, (m) => mkToken('cm', m));
|
|
1021
|
+
src = src.replace(/(\/\*[\s\S]*?\*\/)/g, (m) => mkToken('cm', m));
|
|
1022
|
+
src = src.replace(/(#[^\n]*)/g, (m) => mkToken('cm', m));
|
|
1023
|
+
// Strings
|
|
1024
|
+
src = src.replace(/(["'])(?:[^\\]|\\.)*?\1/g, (m) => mkToken('st', m));
|
|
1025
|
+
src = src.replace(/`([^`]*)`/g, (m) => mkToken('st', m));
|
|
1026
|
+
// Keywords
|
|
1027
|
+
src = src.replace(/\b(function|const|let|var|class|import|export|async|await|return|if|else|for|while|try|catch|throw|new|typeof|instanceof|this|super|switch|case|default|break|continue|do|def|from|elif|except|raise|with|as|lambda|pass|yield|global|nonlocal|public|private|protected|static|final|abstract|interface|extends|implements|package|void)\b/g, (m) => mkToken('kw', m));
|
|
1028
|
+
// Booleans/null
|
|
1029
|
+
src = src.replace(/\b(true|false|null|undefined|None|True|False|nil)\b/g, (m) => mkToken('bl', m));
|
|
1030
|
+
// Numbers
|
|
1031
|
+
src = src.replace(/\b(\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\b/g, (m) => mkToken('nu', m));
|
|
1032
|
+
// Functions
|
|
1033
|
+
src = src.replace(/\b([a-zA-Z_][a-zA-Z0-9_]*)(?=\s*\()/g, (m) => mkToken('fn', m));
|
|
1034
|
+
// Operators
|
|
1035
|
+
src = src.replace(/(===|!==|==|!=|<=|>=|&&|\|\||\+=|-=|\*=|\/=|%=|=>|->)/g, (m) => mkToken('op', m));
|
|
1064
1036
|
}
|
|
1065
1037
|
|
|
1066
|
-
//
|
|
1067
|
-
|
|
1038
|
+
// Now escape HTML on the tokenized source (tokens are safe null-byte markers)
|
|
1039
|
+
let highlighted = esc(src);
|
|
1040
|
+
|
|
1041
|
+
// Replace tokens with actual styled spans
|
|
1042
|
+
const styles = {
|
|
1043
|
+
jk: 'color:#3b82f6;font-weight:600', js: 'color:#10b981', jn: 'color:#f59e0b', jb: 'color:#ef4444',
|
|
1044
|
+
cm: 'color:#6b7280;font-style:italic', st: 'color:#10b981', kw: 'color:#8b5cf6;font-weight:600',
|
|
1045
|
+
bl: 'color:#ef4444', nu: 'color:#f59e0b', fn: 'color:#3b82f6', op: 'color:#a855f7'
|
|
1046
|
+
};
|
|
1047
|
+
for (const { id, cls, text } of tokens) {
|
|
1048
|
+
highlighted = highlighted.replace(id, `<span style="${styles[cls]}">${esc(text)}</span>`);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
return `<pre style="background:#1e293b;padding:1rem;border-radius: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">${highlighted}</pre>`;
|
|
1068
1052
|
}
|
|
1069
1053
|
|
|
1070
1054
|
/**
|
|
@@ -1076,6 +1060,11 @@ class StreamingRenderer {
|
|
|
1076
1060
|
if (typeof data === 'number') return `<span style="color:#7c3aed;font-weight:600">${data}</span>`;
|
|
1077
1061
|
|
|
1078
1062
|
if (typeof data === 'string') {
|
|
1063
|
+
if (data.length > 200 && StreamingRenderer.detectCodeContent(data)) {
|
|
1064
|
+
const displayData = data.length > 1000 ? data.substring(0, 1000) : data;
|
|
1065
|
+
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>` : '';
|
|
1066
|
+
return `<div style="max-height:200px;overflow-y:auto">${StreamingRenderer.renderCodeWithHighlight(displayData, esc)}${suffix}</div>`;
|
|
1067
|
+
}
|
|
1079
1068
|
if (data.length > 500) {
|
|
1080
1069
|
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>`;
|
|
1081
1070
|
}
|