Spaces:
Running
Running
| const form = document.getElementById('chat-form'); | |
| const input = document.getElementById('user-input'); | |
| const sendBtn = document.getElementById('send-btn'); | |
| const chatHistory = document.getElementById('chat-history'); | |
| const apiKeyInput = document.getElementById('api-key'); | |
| const dot = document.getElementById('connection-dot'); | |
| const statusText = document.getElementById('connection-text'); | |
| let conversation = []; | |
| // Auto-adjust textarea height | |
| input.addEventListener('input', function () { | |
| this.style.height = 'auto'; | |
| this.style.height = (this.scrollHeight) + 'px'; | |
| if (this.value.trim() !== '' && apiKeyInput.value.trim() !== '') { | |
| sendBtn.disabled = false; | |
| } else { | |
| sendBtn.disabled = true; | |
| } | |
| }); | |
| input.addEventListener('keydown', function (e) { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| if (!sendBtn.disabled) form.dispatchEvent(new Event('submit')); | |
| } | |
| }); | |
| apiKeyInput.addEventListener('input', () => { | |
| if (apiKeyInput.value.trim().length > 10) { | |
| dot.className = 'dot online'; | |
| statusText.textContent = 'API Key Ready'; | |
| if (input.value.trim() !== '') sendBtn.disabled = false; | |
| } else { | |
| dot.className = 'dot offline'; | |
| statusText.textContent = 'Waiting for key...'; | |
| sendBtn.disabled = true; | |
| } | |
| }); | |
| function appendBubble(role, htmlContent) { | |
| const bubble = document.createElement('div'); | |
| bubble.className = `bubble ${role}`; | |
| const avatar = document.createElement('div'); | |
| avatar.className = 'avatar'; | |
| avatar.innerHTML = role === 'assistant' ? '<i class="fa-solid fa-robot"></i>' : '<i class="fa-solid fa-user"></i>'; | |
| const msg = document.createElement('div'); | |
| msg.className = 'message'; | |
| msg.innerHTML = htmlContent; | |
| bubble.appendChild(avatar); | |
| bubble.appendChild(msg); | |
| chatHistory.appendChild(bubble); | |
| chatHistory.scrollTop = chatHistory.scrollHeight; | |
| return msg; | |
| } | |
| form.addEventListener('submit', async (e) => { | |
| e.preventDefault(); | |
| const userText = input.value.trim(); | |
| if (!userText) return; | |
| const apiKey = apiKeyInput.value.trim(); | |
| const llmModel = document.getElementById('llm-model').value.trim(); | |
| const embedModel = document.getElementById('embed-model').value.trim(); | |
| const endpoint = "https://prod-infinit-memory-production.up.railway.app/v1/chat/completions"; | |
| const username = document.getElementById('username').value.trim() || 'demo_user'; | |
| if (!apiKey) { | |
| alert("Please enter your OpenRouter API Key."); | |
| return; | |
| } | |
| // UI Update | |
| input.value = ''; | |
| input.style.height = 'auto'; | |
| sendBtn.disabled = true; | |
| appendBubble('user', `<p>${userText}</p>`); | |
| conversation.push({ role: "user", content: userText }); | |
| // Show typing | |
| const typingMsg = appendBubble('assistant', '<div class="typing-indicator">Connecting to Backend...<br><small><i>Injecting context and pinging OpenRouter</i></small></div>'); | |
| try { | |
| const payload = { | |
| model: llmModel, | |
| embed_model: embedModel, | |
| user: username, | |
| messages: conversation | |
| }; | |
| const response = await fetch(endpoint, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': `Bearer ${apiKey}` | |
| }, | |
| body: JSON.stringify(payload) | |
| }); | |
| if (!response.ok) { | |
| let errText = await response.text(); | |
| throw new Error(`Server Error (${response.status}): ${errText}`); | |
| } | |
| const data = await response.json(); | |
| const aiAnswer = data.choices[0].message.content; | |
| // Update conversation history | |
| conversation.push({ role: "assistant", content: aiAnswer }); | |
| // Parse markdown and show | |
| typingMsg.innerHTML = marked.parse(aiAnswer); | |
| } catch (err) { | |
| console.error(err); | |
| typingMsg.innerHTML = `<span style="color: #ef4444;">Connection failed: ${err.message}</span>`; | |
| // Remove the failed user message from internal state | |
| conversation.pop(); | |
| } | |
| if (input.value.trim() !== '') sendBtn.disabled = false; | |
| }); | |