From b2a63f44f4f07419d3df1d59daa98ee697a1dc14 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Mon, 30 Jun 2025 15:26:01 -0400 Subject: [PATCH] add auto-scroll to bottom for all chat messages and streaming responses --- uncloseai.js | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/uncloseai.js b/uncloseai.js index 90d7993..ff6a287 100644 --- a/uncloseai.js +++ b/uncloseai.js @@ -1466,19 +1466,21 @@ function openHermesModal() { chatBox.scrollTop = chatBox.scrollHeight; try { - const prompt = `You are Hermes, a large language model from Nous Research. Write a friendly 2-paragraph introduction for yourself when embedded on this webpage. Be specific about this page's content and identify 2-3 key takeaways. Keep it conversational and helpful. + const prompt = `You are Hermes, a large language model from Nous Research. Write a friendly 3-paragraph introduction for yourself when embedded on this webpage. Be specific about this page's content and identify 2-3 key takeaways. Keep it conversational and helpful. Page Title: ${pageTitle} Page URL: ${pageUrl} Page Content: ${pageContent.substring(0, 2000)} -Format: Start with "Greetings! I'm Hermes..." and make it sound natural and engaging. Focus on what YOU can help with regarding THIS specific page.`; +Format: Start with "Greetings! I'm Hermes..." and make it sound natural and engaging. Write 3 full paragraphs that showcase your capabilities and how you can help with THIS specific page.`; let generatedIntro = ''; for await (const chunk of sendMessageDirect(prompt)) { generatedIntro += chunk; // Update display in real-time introDiv.innerHTML = `

🤖 Hermes: ${generatedIntro}

`; + // Scroll to bottom as content updates + chatBox.scrollTop = chatBox.scrollHeight; } // Add to chat history and save @@ -1488,6 +1490,9 @@ Format: Start with "Greetings! I'm Hermes..." and make it sound natural and enga // Cache the generated introduction localStorage.setItem(cacheKey, generatedIntro); + // Add TTS button for introduction + addTTSButtonToIntro(introDiv, generatedIntro); + chatBox.scrollTop = chatBox.scrollHeight; } catch (error) { @@ -1506,9 +1511,67 @@ Format: Start with "Greetings! I'm Hermes..." and make it sound natural and enga introDiv.style.cssText = 'position: relative; margin-bottom: 10px; padding: 10px; border-radius: 5px; background: rgba(0,100,200,0.1); border-left: 4px solid #0066cc;'; introDiv.innerHTML = `

🤖 Hermes: ${introText}

`; chatBox.appendChild(introDiv); + + // Add TTS button for cached introduction + addTTSButtonToIntro(introDiv, introText); + chatBox.scrollTop = chatBox.scrollHeight; } + // Add TTS button to introduction message + function addTTSButtonToIntro(introDiv, introText) { + const ttsIntroBtn = document.createElement('button'); + ttsIntroBtn.textContent = '🔊 Play Response'; + if (USE_CUSTOM_STYLING) { + ttsIntroBtn.style.cssText = 'margin: 5px 0; padding: 6px 12px; border: 1px solid #0066cc; border-radius: 4px; background: #f0f8ff; cursor: pointer; color: #0066cc;'; + } else { + ttsIntroBtn.style.cssText = 'margin: 5px 0; padding: 6px 12px; border-radius: 4px; cursor: pointer;'; + } + + let introAudio = null; + let introBlob = null; + + ttsIntroBtn.onclick = async () => { + if (!introAudio) { + ttsIntroBtn.textContent = 'Processing...'; + ttsIntroBtn.disabled = true; + const selectedVoice = voiceSelect.value; + const result = await speakText(introText, selectedVoice, 0.9); + introAudio = result.audio; + introBlob = result.blob; + ttsIntroBtn.textContent = 'Pause'; + ttsIntroBtn.disabled = false; + introAudio.play(); + + // Add download button for intro + const downloadIntroBtn = document.createElement('button'); + downloadIntroBtn.textContent = '💾 Download'; + if (USE_CUSTOM_STYLING) { + downloadIntroBtn.style.cssText = 'margin: 5px; padding: 6px 12px; border: 1px solid #0066cc; border-radius: 4px; background: #f0f8ff; cursor: pointer; color: #0066cc;'; + } else { + downloadIntroBtn.style.cssText = 'margin: 5px; padding: 6px 12px; border-radius: 4px; cursor: pointer;'; + } + downloadIntroBtn.onclick = () => { + const a = document.createElement('a'); + a.href = URL.createObjectURL(introBlob); + a.download = `hermes-introduction-${Date.now()}.mp3`; + a.click(); + }; + introDiv.appendChild(downloadIntroBtn); + } else { + if (introAudio.paused) { + introAudio.play(); + ttsIntroBtn.textContent = 'Pause'; + } else { + introAudio.pause(); + ttsIntroBtn.textContent = 'Play'; + } + } + }; + + introDiv.appendChild(ttsIntroBtn); + } + // Direct LLM call for introduction generation (doesn't add to chat history) async function* sendMessageDirect(message) { const selectedModel = modelSelect.value || MODEL; @@ -1656,6 +1719,9 @@ Format: Start with "Greetings! I'm Hermes..." and make it sound natural and enga userMessageDiv.innerHTML = `

You: ${userInput}

`; chatBox.appendChild(userMessageDiv); + // Scroll to bottom when user message is added + chatBox.scrollTop = chatBox.scrollHeight; + // Create AI response container const aiMessageDiv = document.createElement('div'); aiMessageDiv.style.cssText = 'position: relative; margin-bottom: 10px; padding: 5px; border-radius: 5px; background: rgba(0,0,0,0.05);'; @@ -1675,6 +1741,9 @@ Format: Start with "Greetings! I'm Hermes..." and make it sound natural and enga responseContent.querySelectorAll('pre code').forEach((block) => { hljs.highlightElement(block); }); + + // Auto-scroll to bottom as response streams in + chatBox.scrollTop = chatBox.scrollHeight; } // Add assistant response to chat history and save