agentgui 1.0.90 → 1.0.92
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/.prd +0 -40
- package/package.json +1 -1
- package/static/index.html +72 -0
- package/static/js/client.js +8 -1
- package/static/js/streaming-renderer.js +43 -1
package/.prd
CHANGED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# AgentGUI HTML Rendering Implementation - IN PROGRESS
|
|
2
|
-
|
|
3
|
-
## Task
|
|
4
|
-
Implement markdown code block parsing within text blocks to enable HTML rendering in conversation messages.
|
|
5
|
-
|
|
6
|
-
## Work Items
|
|
7
|
-
|
|
8
|
-
### 1. Implement parseMarkdownCodeBlocks() in client.js
|
|
9
|
-
- Parse ```language\ncode``` patterns from text blocks
|
|
10
|
-
- Use regex: /```(\w*)\n([\s\S]*?)```/g
|
|
11
|
-
- Return array of parts with type ('text' or 'code') and content/language/code
|
|
12
|
-
- Handle text before, after, and between code blocks
|
|
13
|
-
|
|
14
|
-
### 2. Update renderMessageContent() in client.js
|
|
15
|
-
- For text blocks, check if they contain markdown code blocks
|
|
16
|
-
- If markdown blocks found, parse and render each part
|
|
17
|
-
- For code blocks with language='html', render with innerHTML
|
|
18
|
-
- For other code blocks, render as escaped text with monospace font
|
|
19
|
-
- Apply "Rendered HTML" badge styling for HTML blocks
|
|
20
|
-
|
|
21
|
-
### 3. Add CSS styling for rendered HTML blocks
|
|
22
|
-
- .html-rendered-label: blue background, white text, small font, padding
|
|
23
|
-
- .html-content: white background, border, padding, overflow handling
|
|
24
|
-
- Support both light and dark modes with CSS variables
|
|
25
|
-
|
|
26
|
-
### 4. Test HTML rendering
|
|
27
|
-
- Open "HTML Test" conversation in agent-browser
|
|
28
|
-
- Verify HTML table renders as actual table element
|
|
29
|
-
- Verify "Rendered HTML" badge appears
|
|
30
|
-
- Verify no escaped HTML entities visible
|
|
31
|
-
- Verify no markdown delimiters visible
|
|
32
|
-
- Verify CSS styling applies correctly
|
|
33
|
-
|
|
34
|
-
## Files to Modify
|
|
35
|
-
- /config/workspace/agentgui/static/js/client.js
|
|
36
|
-
- Add parseMarkdownCodeBlocks() method
|
|
37
|
-
- Update renderMessageContent() to use parser for text blocks
|
|
38
|
-
|
|
39
|
-
## Status
|
|
40
|
-
PENDING: Implementation not yet complete
|
package/package.json
CHANGED
package/static/index.html
CHANGED
|
@@ -661,6 +661,78 @@
|
|
|
661
661
|
}
|
|
662
662
|
}
|
|
663
663
|
|
|
664
|
+
/* HTML rendered content blocks */
|
|
665
|
+
.html-rendered-label {
|
|
666
|
+
padding: 0.5rem;
|
|
667
|
+
background: #eff6ff;
|
|
668
|
+
border: 1px solid #bfdbfe;
|
|
669
|
+
border-radius: 0.25rem;
|
|
670
|
+
font-size: 0.75rem;
|
|
671
|
+
font-weight: 600;
|
|
672
|
+
color: #1d4ed8;
|
|
673
|
+
text-transform: uppercase;
|
|
674
|
+
letter-spacing: 0.05em;
|
|
675
|
+
margin-bottom: 0.5rem;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
html.dark .html-rendered-label {
|
|
679
|
+
background: #1e3a5f;
|
|
680
|
+
border-color: #2563eb;
|
|
681
|
+
color: #93c5fd;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
.html-content {
|
|
685
|
+
background: #ffffff;
|
|
686
|
+
padding: 1rem;
|
|
687
|
+
border-radius: 0.375rem;
|
|
688
|
+
border: 1px solid var(--color-border);
|
|
689
|
+
overflow-x: auto;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
html.dark .html-content {
|
|
693
|
+
background: #1f2937;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
.html-content table {
|
|
697
|
+
border-collapse: collapse;
|
|
698
|
+
width: 100%;
|
|
699
|
+
margin: 0.5rem 0;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
.html-content th,
|
|
703
|
+
.html-content td {
|
|
704
|
+
border: 1px solid var(--color-border);
|
|
705
|
+
padding: 0.5rem 0.75rem;
|
|
706
|
+
text-align: left;
|
|
707
|
+
font-size: 0.875rem;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.html-content th {
|
|
711
|
+
background: var(--color-bg-secondary);
|
|
712
|
+
font-weight: 600;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
.html-content ul,
|
|
716
|
+
.html-content ol {
|
|
717
|
+
padding-left: 1.5rem;
|
|
718
|
+
margin: 0.5rem 0;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
.html-content li {
|
|
722
|
+
margin: 0.25rem 0;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
.html-content h1,
|
|
726
|
+
.html-content h2,
|
|
727
|
+
.html-content h3,
|
|
728
|
+
.html-content h4 {
|
|
729
|
+
margin: 0.75rem 0 0.5rem;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
.html-content p {
|
|
733
|
+
margin: 0.5rem 0;
|
|
734
|
+
}
|
|
735
|
+
|
|
664
736
|
/* Syntax highlighting adjustments */
|
|
665
737
|
pre {
|
|
666
738
|
margin: 0;
|
package/static/js/client.js
CHANGED
|
@@ -726,7 +726,14 @@ class AgentGUIClient {
|
|
|
726
726
|
if (msg.content.blocks && Array.isArray(msg.content.blocks)) {
|
|
727
727
|
msg.content.blocks.forEach(block => {
|
|
728
728
|
if (block.type === 'text') {
|
|
729
|
-
|
|
729
|
+
const parts = this.parseMarkdownCodeBlocks(block.text);
|
|
730
|
+
parts.forEach(part => {
|
|
731
|
+
if (part.type === 'text') {
|
|
732
|
+
contentHtml += `<div class="message-text">${this.escapeHtml(part.content)}</div>`;
|
|
733
|
+
} else if (part.type === 'code') {
|
|
734
|
+
contentHtml += this.renderCodeBlock(part.language, part.code);
|
|
735
|
+
}
|
|
736
|
+
});
|
|
730
737
|
} else if (block.type === 'code_block') {
|
|
731
738
|
// Render HTML code blocks as actual HTML elements
|
|
732
739
|
if (block.language === 'html') {
|
|
@@ -569,6 +569,34 @@ class StreamingRenderer {
|
|
|
569
569
|
return div;
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
+
/**
|
|
573
|
+
* Parse markdown code blocks from text
|
|
574
|
+
*/
|
|
575
|
+
parseMarkdownCodeBlocks(text) {
|
|
576
|
+
const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
|
|
577
|
+
const parts = [];
|
|
578
|
+
let lastIndex = 0;
|
|
579
|
+
let match;
|
|
580
|
+
|
|
581
|
+
while ((match = codeBlockRegex.exec(text)) !== null) {
|
|
582
|
+
if (match.index > lastIndex) {
|
|
583
|
+
parts.push({ type: 'text', content: text.substring(lastIndex, match.index) });
|
|
584
|
+
}
|
|
585
|
+
parts.push({ type: 'code', language: match[1] || 'plain', code: match[2] });
|
|
586
|
+
lastIndex = codeBlockRegex.lastIndex;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (lastIndex < text.length) {
|
|
590
|
+
parts.push({ type: 'text', content: text.substring(lastIndex) });
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (parts.length === 0) {
|
|
594
|
+
return [{ type: 'text', content: text }];
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
return parts;
|
|
598
|
+
}
|
|
599
|
+
|
|
572
600
|
/**
|
|
573
601
|
* Render text block event
|
|
574
602
|
*/
|
|
@@ -579,7 +607,21 @@ class StreamingRenderer {
|
|
|
579
607
|
div.dataset.eventType = 'text_block';
|
|
580
608
|
|
|
581
609
|
const text = event.text || event.content || '';
|
|
582
|
-
|
|
610
|
+
const parts = this.parseMarkdownCodeBlocks(text);
|
|
611
|
+
let html = '';
|
|
612
|
+
parts.forEach(part => {
|
|
613
|
+
if (part.type === 'text') {
|
|
614
|
+
html += `<p class="text-sm leading-relaxed">${this.escapeHtml(part.content)}</p>`;
|
|
615
|
+
} else if (part.type === 'code') {
|
|
616
|
+
if (part.language.toLowerCase() === 'html') {
|
|
617
|
+
html += `<div class="html-rendered-label mb-2 p-2 bg-blue-50 rounded border text-xs" style="color:#1d4ed8;background:#eff6ff;border-color:#bfdbfe;">Rendered HTML</div>`;
|
|
618
|
+
html += `<div class="html-content bg-white p-4 rounded border overflow-x-auto" style="background:#fff;border-color:#e5e7eb;">${part.code}</div>`;
|
|
619
|
+
} else {
|
|
620
|
+
html += `<pre class="bg-gray-900 text-gray-100 p-4 rounded overflow-x-auto"><code>${this.escapeHtml(part.code)}</code></pre>`;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
div.innerHTML = html;
|
|
583
625
|
return div;
|
|
584
626
|
}
|
|
585
627
|
|