diff --git a/pkg/channels/http.go b/pkg/channels/http.go
index e46201f23..c05bef4eb 100644
--- a/pkg/channels/http.go
+++ b/pkg/channels/http.go
@@ -7,6 +7,7 @@ import (
"fmt"
"html/template"
"net/http"
+ "regexp"
"strings"
"sync"
"time"
@@ -301,7 +302,24 @@ func renderMarkdown(input string) string {
logger.ErrorCF("http", "renderMarkdown error", map[string]any{"error": err.Error()})
return input // fallback to plain text on error
}
- return buf.String()
+
+ // Add target="_blank" to all links for security and UX
+ html := buf.String()
+
+ // Pattern to match links
+ // This regex adds target="_blank" and rel="noopener noreferrer" to all tags
+ // that don't already have a target attribute
+ re := regexp.MustCompile(`]*?)href="([^"]*?)"([^>]*?)>`)
+ html = re.ReplaceAllStringFunc(html, func(match string) string {
+ // Check if target attribute already exists
+ if strings.Contains(match, `target=`) {
+ return match
+ }
+ // Insert target and rel attributes before closing >
+ return strings.Replace(match, `>`, ` target="_blank" rel="noopener noreferrer">`, 1)
+ })
+
+ return html
}
func min(a, b int) int {
diff --git a/pkg/channels/http_templates/index.html b/pkg/channels/http_templates/index.html
index bfff7ef70..0f8f7c036 100644
--- a/pkg/channels/http_templates/index.html
+++ b/pkg/channels/http_templates/index.html
@@ -17,18 +17,18 @@
display: flex;
justify-content: center;
align-items: center;
- padding: 20px;
+ padding: 10px;
}
.container {
width: 100%;
- max-width: 1200px;
+ max-width: 1400px;
background: #0f0f23;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
overflow: hidden;
display: flex;
flex-direction: column;
- height: 90vh;
+ height: 95vh;
min-height: 600px;
}
.header {
@@ -83,6 +83,7 @@
border-radius: 16px;
line-height: 1.5;
word-wrap: break-word;
+ white-space: normal; /* Evita que los \n del HTML se rendericen como espacios */
}
.message.user {
align-self: flex-end;
@@ -96,6 +97,31 @@
color: #e2e8f0;
border-bottom-left-radius: 4px;
}
+ /* Estilos para tablas en HTTP */
+ .message.assistant table {
+ border-collapse: collapse;
+ width: 100%;
+ max-width: 100%;
+ display: block;
+ overflow-x: auto;
+ margin: 1em 0;
+ border: 1px solid #334155;
+ }
+ .message.assistant th,
+ .message.assistant td {
+ border: 1px solid #475569;
+ padding: 8px 12px;
+ text-align: left;
+ white-space: nowrap; /* Evita saltos dentro de celdas */
+ background: #0f172a;
+ }
+ .message.assistant th {
+ background: #1e293b;
+ font-weight: 600;
+ }
+ .message.assistant tr:nth-child(even) td {
+ background: #162032;
+ }
.message.assistant pre {
background: #0f172a;
padding: 12px;
@@ -253,11 +279,15 @@
function addMessage(content, type) {
const div = document.createElement('div');
div.className = `message ${type}`;
- // Convert newlines to
for proper rendering in HTML
- // For user messages, we need to preserve line breaks from textarea
- let processedContent = content.replace(/\n/g, '
');
- // Also handle double newlines as paragraphs (optional, for better readability)
- processedContent = processedContent.replace(/\n\n/g, '
');
+ let processedContent;
+ if (type === 'user') {
+ // For user messages (plain text), convert newlines to
+ processedContent = content.replace(/\n/g, '
');
+ processedContent = processedContent.replace(/\n\n/g, '
');
+ } else {
+ // For assistant messages (HTML from backend), use as-is
+ processedContent = content;
+ }
div.innerHTML = processedContent;
chatContainer.appendChild(div);
chatContainer.scrollTop = chatContainer.scrollHeight;
diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go
index 77fcfd929..81c405ec3 100644
--- a/pkg/config/defaults.go
+++ b/pkg/config/defaults.go
@@ -114,9 +114,9 @@ func DefaultConfig() *Config {
ReplyTimeout: 5,
},
HTTP: HTTPConfig{
- Enabled: false,
- Host: "0.0.0.0",
- Port: 8080,
+ Enabled: true,
+ Host: "127.0.0.1",
+ Port: 8070,
AllowFrom: FlexibleStringSlice{},
},
},