diff --git a/src/basic/keywords/hear_talk.rs b/src/basic/keywords/hear_talk.rs index 258b949a..bbc3514a 100644 --- a/src/basic/keywords/hear_talk.rs +++ b/src/basic/keywords/hear_talk.rs @@ -96,7 +96,7 @@ pub async fn execute_talk(state: Arc, user: UserSession, message: Stri user_id: "default_user".to_string(), session_id: user.id.to_string(), channel: "web".to_string(), - content: format!("I heard: {}", message), + content: message, message_type: 1, stream_token: None, is_complete: true, diff --git a/web/html/index.html b/web/html/index.html index 4812834a..0e9ac2ac 100644 --- a/web/html/index.html +++ b/web/html/index.html @@ -22,6 +22,17 @@ --text-secondary: #a0a0b0; } + [data-theme="light"] { + --primary: #0066cc; + --primary-glow: rgba(0, 102, 204, 0.3); + --secondary: #cc00cc; + --accent: #ff9900; + --bg-dark: #f5f7fa; + --bg-card: rgba(255, 255, 255, 0.9); + --text-primary: #1a1a1a; + --text-secondary: #666666; + } + * { margin: 0; padding: 0; @@ -34,6 +45,11 @@ color: var(--text-primary); overflow: hidden; position: relative; + transition: background 0.3s ease, color 0.3s ease; + } + + [data-theme="light"] body { + background: radial-gradient(ellipse at top, #e6e9f0 0%, #f5f7fa 100%); } body::before { @@ -50,6 +66,12 @@ z-index: 0; } + [data-theme="light"] body::before { + background: + radial-gradient(circle at 20% 50%, rgba(0, 102, 204, 0.1) 0%, transparent 50%), + radial-gradient(circle at 80% 80%, rgba(204, 0, 204, 0.1) 0%, transparent 50%); + } + .grain-overlay { position: fixed; top: 0; @@ -62,6 +84,10 @@ opacity: 0.4; } + [data-theme="light"] .grain-overlay { + opacity: 0.1; + } + .sidebar { position: fixed; left: -320px; @@ -78,6 +104,12 @@ box-shadow: 10px 0 50px rgba(0, 0, 0, 0.5); } + [data-theme="light"] .sidebar { + background: linear-gradient(135deg, rgba(255, 255, 255, 0.98) 0%, rgba(245, 247, 250, 0.98) 100%); + border-right: 1px solid rgba(0, 102, 204, 0.2); + box-shadow: 10px 0 50px rgba(0, 0, 0, 0.1); + } + .sidebar.open { left: 0; } @@ -103,12 +135,23 @@ backdrop-filter: blur(20px); } + [data-theme="light"] .sidebar-toggle { + background: rgba(0, 102, 204, 0.1); + border: 1px solid rgba(0, 102, 204, 0.3); + color: var(--primary); + } + .sidebar-toggle:hover { background: rgba(0, 240, 255, 0.2); transform: scale(1.05); box-shadow: 0 0 30px var(--primary-glow); } + [data-theme="light"] .sidebar-toggle:hover { + background: rgba(0, 102, 204, 0.2); + box-shadow: 0 0 30px var(--primary-glow); + } + .new-chat { width: 100%; padding: 16px; @@ -125,12 +168,23 @@ backdrop-filter: blur(10px); } + [data-theme="light"] .new-chat { + background: linear-gradient(135deg, rgba(0, 102, 204, 0.15) 0%, rgba(204, 0, 204, 0.15) 100%); + border: 1px solid rgba(0, 102, 204, 0.3); + color: var(--primary); + } + .new-chat:hover { background: linear-gradient(135deg, rgba(0, 240, 255, 0.25) 0%, rgba(255, 0, 229, 0.25) 100%); transform: translateY(-2px); box-shadow: 0 10px 30px rgba(0, 240, 255, 0.3); } + [data-theme="light"] .new-chat:hover { + background: linear-gradient(135deg, rgba(0, 102, 204, 0.25) 0%, rgba(204, 0, 204, 0.25) 100%); + box-shadow: 0 10px 30px rgba(0, 102, 204, 0.3); + } + .voice-toggle { width: 100%; padding: 16px; @@ -146,11 +200,21 @@ backdrop-filter: blur(10px); } + [data-theme="light"] .voice-toggle { + background: rgba(0, 200, 83, 0.1); + border: 1px solid rgba(0, 200, 83, 0.3); + color: #00c853; + } + .voice-toggle:hover { background: rgba(100, 255, 180, 0.2); transform: translateY(-2px); } + [data-theme="light"] .voice-toggle:hover { + background: rgba(0, 200, 83, 0.2); + } + .voice-toggle.recording { background: rgba(255, 100, 120, 0.2); border-color: rgba(255, 100, 120, 0.4); @@ -158,11 +222,22 @@ animation: recordingPulse 2s infinite; } + [data-theme="light"] .voice-toggle.recording { + background: rgba(244, 67, 54, 0.2); + border-color: rgba(244, 67, 54, 0.4); + color: #f44336; + } + @keyframes recordingPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(255, 100, 120, 0.4); } 50% { box-shadow: 0 0 20px 10px rgba(255, 100, 120, 0); } } + [data-theme="light"] @keyframes recordingPulse { + 0%, 100% { box-shadow: 0 0 0 0 rgba(244, 67, 54, 0.4); } + 50% { box-shadow: 0 0 20px 10px rgba(244, 67, 54, 0); } + } + .history-item { padding: 12px; margin-bottom: 8px; @@ -175,12 +250,22 @@ word-wrap: break-word; } + [data-theme="light"] .history-item { + background: rgba(0, 0, 0, 0.03); + border: 1px solid rgba(0, 0, 0, 0.05); + } + .history-item:hover { background: rgba(0, 240, 255, 0.1); border-color: rgba(0, 240, 255, 0.3); transform: translateX(4px); } + [data-theme="light"] .history-item:hover { + background: rgba(0, 102, 204, 0.1); + border-color: rgba(0, 102, 204, 0.3); + } + .main { margin-left: 0; width: 100%; @@ -207,6 +292,11 @@ justify-content: space-between; } + [data-theme="light"] header { + background: rgba(255, 255, 255, 0.7); + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + } + .logo { display: flex; align-items: center; @@ -224,8 +314,16 @@ font-size: 28px; font-weight: 700; color: #fff; - box-shadow: 0 8px 32px rgba(0, 240, 255, 0.4); + box-shadow: 0 8px 32px var(--primary-glow); position: relative; + overflow: hidden; + } + + .logo-icon img { + width: 100%; + height: 100%; + object-fit: contain; + padding: 6px; } .logo-icon::before { @@ -295,6 +393,14 @@ margin-bottom: 24px; position: relative; animation: floatIcon 3s ease-in-out infinite; + overflow: hidden; + } + + .empty-icon img { + width: 100%; + height: 100%; + object-fit: contain; + padding: 12px; } .empty-icon::before { @@ -358,6 +464,12 @@ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); } + [data-theme="light"] .user-message-content { + background: linear-gradient(135deg, rgba(0, 102, 204, 0.15) 0%, rgba(204, 0, 204, 0.15) 100%); + border: 1px solid rgba(0, 102, 204, 0.3); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + } + .assistant-message { display: flex; gap: 16px; @@ -376,8 +488,16 @@ font-weight: 700; color: #fff; flex-shrink: 0; - box-shadow: 0 8px 24px rgba(0, 240, 255, 0.3); + box-shadow: 0 8px 24px var(--primary-glow); position: relative; + overflow: hidden; + } + + .assistant-avatar img { + width: 100%; + height: 100%; + object-fit: contain; + padding: 6px; } .assistant-avatar::before { @@ -403,6 +523,12 @@ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); } + [data-theme="light"] .assistant-message-content { + background: rgba(0, 0, 0, 0.03); + border: 1px solid rgba(0, 0, 0, 0.08); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + } + .thinking-indicator { display: flex; gap: 16px; @@ -441,6 +567,11 @@ position: relative; } + [data-theme="light"] footer { + background: rgba(255, 255, 255, 0.7); + border-top: 1px solid rgba(0, 0, 0, 0.05); + } + .suggestions-container { display: flex; flex-wrap: wrap; @@ -462,12 +593,22 @@ backdrop-filter: blur(10px); } + [data-theme="light"] .suggestion-button { + background: rgba(0, 102, 204, 0.1); + border: 1px solid rgba(0, 102, 204, 0.3); + } + .suggestion-button:hover { background: rgba(0, 240, 255, 0.2); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0, 240, 255, 0.3); } + [data-theme="light"] .suggestion-button:hover { + background: rgba(0, 102, 204, 0.2); + box-shadow: 0 8px 24px rgba(0, 102, 204, 0.3); + } + .input-container { display: flex; gap: 12px; @@ -490,12 +631,24 @@ backdrop-filter: blur(10px); } + [data-theme="light"] #messageInput { + background: rgba(0, 0, 0, 0.05); + border: 1px solid rgba(0, 0, 0, 0.1); + color: var(--text-primary); + } + #messageInput:focus { border-color: rgba(0, 240, 255, 0.5); background: rgba(255, 255, 255, 0.08); box-shadow: 0 0 30px rgba(0, 240, 255, 0.2); } + [data-theme="light"] #messageInput:focus { + border-color: rgba(0, 102, 204, 0.5); + background: rgba(0, 0, 0, 0.08); + box-shadow: 0 0 30px rgba(0, 102, 204, 0.2); + } + #messageInput::placeholder { color: var(--text-secondary); } @@ -510,7 +663,7 @@ font-size: 15px; cursor: pointer; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - box-shadow: 0 8px 24px rgba(0, 240, 255, 0.4); + box-shadow: 0 8px 24px var(--primary-glow); position: relative; overflow: hidden; } @@ -530,7 +683,7 @@ #sendBtn:hover { transform: translateY(-2px); - box-shadow: 0 12px 36px rgba(0, 240, 255, 0.6); + box-shadow: 0 12px 36px var(--primary-glow); } #newChatBtn { @@ -546,12 +699,22 @@ backdrop-filter: blur(10px); } + [data-theme="light"] #newChatBtn { + background: rgba(0, 102, 204, 0.1); + border: 1px solid rgba(0, 102, 204, 0.3); + } + #newChatBtn:hover { background: rgba(0, 240, 255, 0.2); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0, 240, 255, 0.3); } + [data-theme="light"] #newChatBtn:hover { + background: rgba(0, 102, 204, 0.2); + box-shadow: 0 8px 24px rgba(0, 102, 204, 0.3); + } + .voice-status { background: rgba(100, 255, 180, 0.15); border-bottom: 1px solid rgba(100, 255, 180, 0.3); @@ -562,6 +725,12 @@ backdrop-filter: blur(20px); } + [data-theme="light"] .voice-status { + background: rgba(0, 200, 83, 0.15); + border-bottom: 1px solid rgba(0, 200, 83, 0.3); + color: #00c853; + } + .warning-message { background: rgba(255, 200, 0, 0.1); border: 1px solid rgba(255, 200, 0, 0.3); @@ -572,6 +741,12 @@ backdrop-filter: blur(10px); } + [data-theme="light"] .warning-message { + background: rgba(255, 152, 0, 0.1); + border: 1px solid rgba(255, 152, 0, 0.3); + color: #ff9800; + } + .connection-status { position: fixed; top: 24px; @@ -594,11 +769,21 @@ animation: connectedPulse 2s infinite; } + [data-theme="light"] .connection-status.connected { + background-color: #00c853; + box-shadow: 0 0 20px rgba(0, 200, 83, 0.6); + } + .connection-status.disconnected { background-color: #ff6478; box-shadow: 0 0 20px rgba(255, 100, 120, 0.6); } + [data-theme="light"] .connection-status.disconnected { + background-color: #f44336; + box-shadow: 0 0 20px rgba(244, 67, 54, 0.6); + } + @keyframes connectingPulse { 0%, 100% { opacity: 0.6; transform: scale(0.8); } 50% { opacity: 1; transform: scale(1.2); } @@ -609,6 +794,11 @@ 50% { opacity: 1; transform: scale(1.3); box-shadow: 0 0 30px rgba(100, 255, 180, 0.8); } } + [data-theme="light"] @keyframes connectedPulse { + 0%, 100% { opacity: 0.8; transform: scale(1); } + 50% { opacity: 1; transform: scale(1.3); box-shadow: 0 0 30px rgba(0, 200, 83, 0.8); } + } + .markdown-content h1, .markdown-content h2, .markdown-content h3 { @@ -650,6 +840,12 @@ border: 1px solid rgba(0, 240, 255, 0.2); } + [data-theme="light"] .markdown-content code { + background: rgba(0, 102, 204, 0.1); + color: var(--primary); + border: 1px solid rgba(0, 102, 204, 0.2); + } + .markdown-content pre { background: rgba(0, 0, 0, 0.4); border: 1px solid rgba(255, 255, 255, 0.1); @@ -660,6 +856,11 @@ backdrop-filter: blur(10px); } + [data-theme="light"] .markdown-content pre { + background: rgba(0, 0, 0, 0.05); + border: 1px solid rgba(0, 0, 0, 0.1); + } + .markdown-content pre code { background: none; padding: 0; @@ -667,6 +868,10 @@ color: #e0e0e0; } + [data-theme="light"] .markdown-content pre code { + color: #333333; + } + .markdown-content table { width: 100%; border-collapse: collapse; @@ -680,12 +885,21 @@ text-align: left; } + [data-theme="light"] .markdown-content table th, + [data-theme="light"] .markdown-content table td { + border: 1px solid rgba(0, 0, 0, 0.1); + } + .markdown-content table th { background: rgba(0, 240, 255, 0.1); font-weight: 600; color: var(--primary); } + [data-theme="light"] .markdown-content table th { + background: rgba(0, 102, 204, 0.1); + } + .markdown-content blockquote { border-left: 3px solid var(--primary); padding-left: 20px; @@ -711,6 +925,10 @@ transition: all 0.3s; } + [data-theme="light"] .markdown-content a { + border-bottom: 1px solid rgba(0, 102, 204, 0.3); + } + .markdown-content a:hover { border-bottom-color: var(--primary); } @@ -723,15 +941,27 @@ background: rgba(255, 255, 255, 0.02); } + [data-theme="light"] ::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.02); + } + ::-webkit-scrollbar-thumb { background: rgba(0, 240, 255, 0.3); border-radius: 5px; } + [data-theme="light"] ::-webkit-scrollbar-thumb { + background: rgba(0, 102, 204, 0.3); + } + ::-webkit-scrollbar-thumb:hover { background: rgba(0, 240, 255, 0.5); } + [data-theme="light"] ::-webkit-scrollbar-thumb:hover { + background: rgba(0, 102, 204, 0.5); + } + .scroll-to-bottom { position: absolute; bottom: 24px; @@ -747,14 +977,14 @@ display: flex; align-items: center; justify-content: center; - box-shadow: 0 8px 24px rgba(0, 240, 255, 0.4); + box-shadow: 0 8px 24px var(--primary-glow); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); z-index: 10; } .scroll-to-bottom:hover { transform: scale(1.1); - box-shadow: 0 12px 36px rgba(0, 240, 255, 0.6); + box-shadow: 0 12px 36px var(--primary-glow); } .continue-button { @@ -771,12 +1001,22 @@ font-size: 14px; } + [data-theme="light"] .continue-button { + background: rgba(0, 102, 204, 0.1); + border: 1px solid rgba(0, 102, 204, 0.3); + } + .continue-button:hover { background: rgba(0, 240, 255, 0.2); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0, 240, 255, 0.3); } + [data-theme="light"] .continue-button:hover { + background: rgba(0, 102, 204, 0.2); + box-shadow: 0 8px 24px rgba(0, 102, 204, 0.3); + } + .context-indicator { position: fixed; bottom: 110px; @@ -793,6 +1033,12 @@ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); } + [data-theme="light"] .context-indicator { + background: rgba(255, 255, 255, 0.95); + border: 1px solid rgba(0, 102, 204, 0.3); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + } + .context-progress { height: 6px; background: rgba(255, 255, 255, 0.1); @@ -801,6 +1047,10 @@ overflow: hidden; } + [data-theme="light"] .context-progress { + background: rgba(0, 0, 0, 0.1); + } + .context-progress-bar { height: 100%; background: linear-gradient(90deg, #64ffb4, var(--primary)); @@ -808,14 +1058,63 @@ transition: width 0.3s ease, background-color 0.3s ease; } + [data-theme="light"] .context-progress-bar { + background: linear-gradient(90deg, #00c853, var(--primary)); + } + .context-progress-bar.warning { background: linear-gradient(90deg, #ffc800, var(--accent)); } + [data-theme="light"] .context-progress-bar.warning { + background: linear-gradient(90deg, #ff9800, var(--accent)); + } + .context-progress-bar.danger { background: linear-gradient(90deg, #ff6478, var(--secondary)); } + [data-theme="light"] .context-progress-bar.danger { + background: linear-gradient(90deg, #f44336, var(--secondary)); + } + + .theme-toggle { + position: fixed; + top: 24px; + right: 60px; + z-index: 101; + background: rgba(0, 240, 255, 0.1); + border: 1px solid rgba(0, 240, 255, 0.3); + color: var(--primary); + padding: 12px; + border-radius: 12px; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + font-size: 20px; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + backdrop-filter: blur(20px); + } + + [data-theme="light"] .theme-toggle { + background: rgba(0, 102, 204, 0.1); + border: 1px solid rgba(0, 102, 204, 0.3); + } + + .theme-toggle:hover { + background: rgba(0, 240, 255, 0.2); + transform: scale(1.05); + box-shadow: 0 0 30px var(--primary-glow); + } + + [data-theme="light"] .theme-toggle:hover { + background: rgba(0, 102, 204, 0.2); + box-shadow: 0 0 30px var(--primary-glow); + } + @media (max-width: 768px) { .sidebar { width: 100%; @@ -884,6 +1183,13 @@ right: 20px; width: 120px; } + + .theme-toggle { + top: 16px; + right: 60px; + width: 44px; + height: 44px; + } } @media (max-width: 480px) { @@ -921,6 +1227,13 @@ height: 40px; font-size: 16px; } + + .theme-toggle { + top: 16px; + right: 60px; + width: 40px; + height: 40px; + } } @@ -929,6 +1242,7 @@
+ @@ -1139,6 +1344,7 @@ let contextUsage = 0; let isUserScrolling = false; let autoScrollEnabled = true; + let currentTheme = 'dark'; const messagesDiv = document.getElementById("messages"); const input = document.getElementById("messageInput"); @@ -1149,6 +1355,7 @@ const contextIndicator = document.getElementById("contextIndicator"); const contextPercentage = document.getElementById("contextPercentage"); const contextProgressBar = document.getElementById("contextProgressBar"); + const themeToggle = document.getElementById("themeToggle"); marked.setOptions({ breaks: true, @@ -1159,6 +1366,15 @@ document.getElementById("sidebar").classList.toggle("open"); } + function toggleTheme() { + currentTheme = currentTheme === 'dark' ? 'light' : 'dark'; + document.documentElement.setAttribute('data-theme', currentTheme); + themeToggle.textContent = currentTheme === 'dark' ? '🌙' : '☀️'; + + // Save theme preference to localStorage + localStorage.setItem('gb-theme', currentTheme); + } + function updateConnectionStatus(status) { connectionStatus.className = `connection-status ${status}`; } @@ -1171,6 +1387,19 @@ } window.addEventListener("load", function () { + // Check for saved theme preference or respect OS preference + const savedTheme = localStorage.getItem('gb-theme'); + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + + if (savedTheme) { + currentTheme = savedTheme; + } else { + currentTheme = prefersDark ? 'dark' : 'light'; + } + + document.documentElement.setAttribute('data-theme', currentTheme); + themeToggle.textContent = currentTheme === 'dark' ? '🌙' : '☀️'; + input.focus(); }); @@ -1274,7 +1503,9 @@ loadSessions(); document.getElementById("messages").innerHTML = `
-
D
+
+ General Bots Logo +

Bem-vindo ao General Bots

Seu assistente de IA avançado

@@ -1316,7 +1547,9 @@ if (history.length === 0) { messages.innerHTML = `
-
D
+
+ General Bots Logo +

Bem-vindo ao General Bots

Seu assistente de IA avançado

@@ -1457,7 +1690,9 @@ thinkingDiv.className = "message-container"; thinkingDiv.innerHTML = `
-
D
+
+ General Bots Logo +
@@ -1549,7 +1784,9 @@ continueDiv.className = "message-container"; continueDiv.innerHTML = `
-
D
+
+ General Bots Logo +

A conexão foi interrompida. Clique em "Continuar" para tentar recuperar a resposta.

@@ -1622,7 +1859,9 @@ } else if (role === "assistant") { msg.innerHTML = `
-
D
+
+ General Bots Logo +
${streaming ? "" : marked.parse(content)}
@@ -1639,7 +1878,9 @@ } else { msg.innerHTML = `
-
D
+
+ General Bots Logo +
${content}
`; @@ -1694,6 +1935,118 @@ return div.innerHTML; } + function handleSuggestions(suggestions) { + const footer = document.querySelector('footer'); + let container = footer.querySelector('.suggestions-container'); + + if (!container) { + container = document.createElement('div'); + container.className = 'suggestions-container'; + footer.insertBefore(container, footer.firstChild); + } + + container.innerHTML = ''; + suggestions.forEach(s => { + const btn = document.createElement('button'); + btn.textContent = s.text; + btn.className = 'suggestion-button'; + btn.onclick = () => { + setContext(s.context); + input.value = ''; + }; + container.appendChild(btn); + }); + } + + let pendingContextChange = null; + + async function setContext(context) { + try { + const buttonText = event?.target?.textContent || context; + + addMessage("user", buttonText); + + const input = document.getElementById('messageInput'); + if (input) { + input.value = ''; + } + + if (ws && ws.readyState === WebSocket.OPEN) { + pendingContextChange = new Promise((resolve) => { + const handler = (event) => { + const response = JSON.parse(event.data); + if (response.message_type === 5 && response.context_name === context) { + ws.removeEventListener('message', handler); + resolve(); + } + }; + ws.addEventListener('message', handler); + + const suggestionEvent = { + bot_id: currentBotId, + user_id: currentUserId, + session_id: currentSessionId, + channel: "web", + content: buttonText, + message_type: 4, + is_suggestion: true, + context_name: context, + timestamp: new Date().toISOString() + }; + ws.send(JSON.stringify(suggestionEvent)); + }); + + await pendingContextChange; + const contextIndicator = document.getElementById('contextIndicator'); + if (contextIndicator) { + contextIndicator.style.display = 'block'; + document.getElementById('contextPercentage').textContent = context; + } + } else { + console.warn("WebSocket não está conectado. Tentando reconectar..."); + connectWebSocket(); + } + } catch (err) { + console.error('Failed to set context:', err); + } + } + + async function sendMessage() { + if (pendingContextChange) { + await pendingContextChange; + pendingContextChange = null; + } + const message = input.value.trim(); + if (!message || !ws || ws.readyState !== WebSocket.OPEN) { + if (!ws || ws.readyState !== WebSocket.OPEN) { + showWarning("Conexão não disponível. Tentando reconectar..."); + connectWebSocket(); + } + return; + } + + if (isThinking) { + hideThinkingIndicator(); + } + + addMessage("user", message); + + const messageData = { + bot_id: currentBotId, + user_id: currentUserId, + session_id: currentSessionId, + channel: "web", + content: message, + message_type: 1, + media_url: null, + timestamp: new Date().toISOString() + }; + + ws.send(JSON.stringify(messageData)); + input.value = ""; + input.focus(); + } + sendBtn.onclick = sendMessage; input.addEventListener("keypress", (e) => { if (e.key === "Enter") sendMessage();