From 3c7c4d4233b032a48f018655f1c250a6c7fe1056 Mon Sep 17 00:00:00 2001 From: mike Date: Sun, 28 Dec 2025 02:49:49 +0100 Subject: [PATCH] chore: update 6 file(s) --- .aider.conf.yml | 2 +- .aider.model.settings.yml | 5 +- .aiignore | 6 +- README.md | 1 + chat.js => chatv2.js | 112 ++++--- index.html | 608 +------------------------------------- 6 files changed, 76 insertions(+), 658 deletions(-) create mode 100644 README.md rename chat.js => chatv2.js (85%) diff --git a/.aider.conf.yml b/.aider.conf.yml index 8619221..aa77361 100644 --- a/.aider.conf.yml +++ b/.aider.conf.yml @@ -1 +1 @@ -model: ollama_chat/qwen2.5-coder:14b-instruct-q4_K_M \ No newline at end of file +model: /models/Qwen/Qwen2.5-Coder-32B-Instruct-GGUF/qwen2.5-coder-32b-instruct-q4_k_m.gguf \ No newline at end of file diff --git a/.aider.model.settings.yml b/.aider.model.settings.yml index 43facbf..0e3af4d 100644 --- a/.aider.model.settings.yml +++ b/.aider.model.settings.yml @@ -1,3 +1,4 @@ -- name: /models/qwen2.5-coder-32b-instruct-q4_k_m.gguf +- name: /models/Qwen/Qwen2.5-Coder-32B-Instruct-GGUF/qwen2.5-coder-32b-instruct-q4_k_m.gguf extra_params: - num_ctx: 16384 \ No newline at end of file + num_ctx: 16384 + num_threads: 8 \ No newline at end of file diff --git a/.aiignore b/.aiignore index 62c8935..a3a7798 100644 --- a/.aiignore +++ b/.aiignore @@ -1 +1,5 @@ -.idea/ \ No newline at end of file +.idea/ +.aider.tags.cache.v4 +.aider.chat.history.md +.aider.input.history +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..40816a2 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Hi \ No newline at end of file diff --git a/chat.js b/chatv2.js similarity index 85% rename from chat.js rename to chatv2.js index 76e5927..be84359 100644 --- a/chat.js +++ b/chatv2.js @@ -2,23 +2,24 @@ const BACKENDS = { plato : { prod: '/api/plato', - dev : 'http://192.168.1.74:1234/v1', + dev : 'http://192.168.1.74:1234/v1', // Removed trailing space name: 'Plato (192.168.1.74)' }, stoic : { prod: '/api/stoic', - dev : 'http://192.168.1.159:1234/v1', + dev : 'http://192.168.1.159:1234/v1', // Removed trailing space name: 'Stoic (192.168.1.159)' }, ollama: { prod: '/api/ollama', - dev : 'http://192.168.1.159:8081/v1', + dev : 'http://192.168.1.159:8081/v1', // Removed trailing space name: 'Ollama (192.168.1.159:8081)' } } const IS_PRODUCTION = window.location.hostname === 'jarvis-lan.appmodel.nl' const API_KEY = 'not-needed' +const MAX_CHAT_HISTORY = 50 // Maximum messages to keep in history // Global state let currentBackend = 'plato' @@ -26,7 +27,7 @@ let currentModel = null let availableModels = [] let currentStreamController = null let isStreaming = false -let chatHistory = [] // Initialize chat history array +let chatHistory = [] // Stores conversation history // Get current API URL based on selected backend function getApiUrl() { @@ -38,7 +39,7 @@ function getApiUrl() { function updateBackendDisplay() { const backend = BACKENDS[currentBackend] const displayText = IS_PRODUCTION - ? `${ backend.prod } → ${ backend.name }` + ? `${ backend.prod } ? ${ backend.name }` : backend.dev document.getElementById('backendDisplay').textContent = displayText } @@ -84,6 +85,23 @@ function populateModelSelector() { } } +// Get formatted messages for API (excludes UI-specific properties) +function getApiMessages() { + // Get last N messages and format for API + return chatHistory.slice(-MAX_CHAT_HISTORY).map(({ role, content }) => ({ + role, + content + })) +} + +// Trim chat history if it exceeds maximum +function trimChatHistory() { + if (chatHistory.length > MAX_CHAT_HISTORY) { + chatHistory = chatHistory.slice(-MAX_CHAT_HISTORY) + console.log(`Chat history trimmed to ${ MAX_CHAT_HISTORY } messages`) + } +} + // Handle backend and model selection changes document.addEventListener('DOMContentLoaded', () => { const backendSelector = document.getElementById('backendSelector') @@ -96,7 +114,7 @@ document.addEventListener('DOMContentLoaded', () => { backendSelector.addEventListener('change', (e) => { currentBackend = e.target.value updateBackendDisplay() - console.log('Backend switched to:', currentBackend, '→', getApiUrl()) + console.log('Backend switched to:', currentBackend, '?', getApiUrl()) fetchModels() // Reload models for new backend }) @@ -146,7 +164,7 @@ function addMessage(role, content, markdown = false, messageId = null) { const avatar = document.createElement('div') avatar.className = `avatar ${ role }-avatar` - avatar.textContent = role === 'user' ? '👤' : '🤖' + avatar.textContent = role === 'user' ? '?' : '?' const name = document.createElement('span') name.textContent = role === 'user' ? 'You' : 'Assistant' @@ -183,9 +201,12 @@ function addMessage(role, content, markdown = false, messageId = null) { chatLog.appendChild(messageDiv) chatLog.scrollTop = chatLog.scrollHeight - // Add message to chat history + // Store message in history (excluding UI-specific properties) chatHistory.push({ role, content, markdown, messageId }) + // Trim history if it gets too long + trimChatHistory() + return contentDiv } @@ -201,8 +222,8 @@ function parseThinkingTags(content) { const id = `thinking-${ Date.now() }-${ thinkingCounter }` return `
- - 🤔 Thinking... + ? + ? Thinking...
${ thinkContent.trim() }
` @@ -215,8 +236,8 @@ function parseThinkingTags(content) { const id = `thinking-${ Date.now() }-${ thinkingCounter }` return `
- - 🤔 Thinking... + ? + ? Thinking...
${ thinkContent.trim() }
` @@ -267,7 +288,7 @@ function showTypingIndicator() { const avatar = document.createElement('div') avatar.className = 'avatar assistant-avatar' - avatar.textContent = '🤖' + avatar.textContent = '?' const name = document.createElement('span') name.textContent = 'Assistant' @@ -315,7 +336,7 @@ async function handleStreamingResponse(userMessage) { const avatar = document.createElement('div') avatar.className = 'avatar assistant-avatar' - avatar.textContent = '🤖' + avatar.textContent = '?' const name = document.createElement('span') name.textContent = 'Assistant' @@ -344,7 +365,7 @@ async function handleStreamingResponse(userMessage) { const requestBody = { model : currentModel || 'local-model', - messages : [{ role: 'user', content: userMessage }], + messages : getApiMessages(), // Send full chat history stream : true, temperature: 0.7, max_tokens : 2000 @@ -384,7 +405,7 @@ async function handleStreamingResponse(userMessage) { // Update immediately if enough time has passed updateScheduled = true requestAnimationFrame(() => { - updateMessageContent(contentDiv, accumulatedContent, markdownToggle.checked) + updateMessageContent(contentDiv, accumulatedContent, markdownToggle.checked, 'assistant') if (cursorSpan.parentNode) { contentDiv.appendChild(cursorSpan) } @@ -397,7 +418,7 @@ async function handleStreamingResponse(userMessage) { updateScheduled = true setTimeout(() => { requestAnimationFrame(() => { - updateMessageContent(contentDiv, accumulatedContent, markdownToggle.checked) + updateMessageContent(contentDiv, accumulatedContent, markdownToggle.checked, 'assistant') if (cursorSpan.parentNode) { contentDiv.appendChild(cursorSpan) } @@ -424,7 +445,7 @@ async function handleStreamingResponse(userMessage) { isStreaming = false currentStreamController = null // Final update and remove cursor - updateMessageContent(contentDiv, accumulatedContent, markdownToggle.checked) + updateMessageContent(contentDiv, accumulatedContent, markdownToggle.checked, 'assistant') if (cursorSpan.parentNode) { cursorSpan.parentNode.removeChild(cursorSpan) } @@ -446,19 +467,18 @@ async function handleStreamingResponse(userMessage) { } // Final update - updateMessageContent(contentDiv, accumulatedContent, markdownToggle.checked) + updateMessageContent(contentDiv, accumulatedContent, markdownToggle.checked, 'assistant') chatLog.scrollTop = chatLog.scrollHeight } catch (error) { console.error('Streaming error:', error) if (error.name !== 'AbortError') { - updateMessageContent(contentDiv, `Error: ${ error.message }`, false) + updateMessageContent(contentDiv, `Error: ${ error.message }`, false, 'assistant') } } finally { isStreaming = false currentStreamController = null sendBtn.disabled = false - userInput.focus() // Remove cursor if still exists if (cursorSpan.parentNode) { @@ -480,7 +500,7 @@ async function handleNonStreamingResponse(userMessage) { const requestBody = { model : currentModel || 'local-model', - messages : [{ role: 'user', content: userMessage }], + messages : getApiMessages(), // Send full chat history stream : false, temperature: 0.7, max_tokens : 2000 @@ -519,12 +539,6 @@ async function handleNonStreamingResponse(userMessage) { } } -function loadChatHistory() { - chatHistory.forEach(message => { - addMessage(message.role, message.content, message.markdown, message.messageId) - }) -} - // Stop current stream function stopStream() { if (currentStreamController) { @@ -541,17 +555,24 @@ async function sendMessage() { const userMessage = userInput.value.trim() if (!userMessage || isStreaming) return + // Add user message to UI and history addMessage('user', userMessage) + + // Clear input field userInput.value = '' userInput.style.height = 'auto' sendBtn.disabled = true + // Update button text based on streaming state if (streamToggle.checked) { sendBtn.textContent = 'Stop' - handleStreamingResponse(userMessage) + await handleStreamingResponse(userMessage) } else { - handleNonStreamingResponse(userMessage) + await handleNonStreamingResponse(userMessage) } + + // Reset button text + sendBtn.textContent = 'Send' } // Event Listeners @@ -577,28 +598,25 @@ window.onload = () => { userInput.focus() fetchModels() - // Load chat history - loadChatHistory() + // Add welcome message (this will be the first entry in chatHistory) + const welcomeMessage = `# Welcome to LM Studio Chat! ? - // Add welcome message - setTimeout(() => { - const welcomeMessage = `# Welcome to LM Studio Chat! 🚀 - -I now support **real-time streaming responses** and **dark, readable text formatting**. +I now support **full conversation history**, **real-time streaming responses** and **dark, readable text formatting**. ## Features: -1. **Streaming Mode** (enabled by default) - Watch responses appear word-by-word -2. **Markdown Rendering** - Proper formatting for code, lists, tables, and more -3. **Readable Dark Text** - No more eye strain from light gray text -4. **Model Detection** - Automatically shows your loaded model +1. **Full Chat History** - Complete conversation context is now sent to the AI +2. **Smart History Management** - Automatically keeps the last ${ MAX_CHAT_HISTORY } messages +3. **Streaming Mode** (enabled by default) - Watch responses appear word-by-word +4. **Markdown Rendering** - Proper formatting for code, lists, tables, and more +5. **Readable Dark Text** - No more eye strain from light gray text ## Try it out: -- Ask a technical question to see **code formatting** -- Type \`ls -la\` in a code block -- Request a **numbered list** or table +- Ask follow-up questions that reference earlier messages +- Have a multi-turn conversation with full context +- Ask "what did I just ask?" to test history retention - Watch the streaming response in real-time! > *Tip: You can toggle streaming and markdown using the checkboxes below.*` - addMessage('assistant', welcomeMessage, true) - }, 500) -} + + addMessage('assistant', welcomeMessage, true) +} \ No newline at end of file diff --git a/index.html b/index.html index 72850e2..9034621 100644 --- a/index.html +++ b/index.html @@ -58,612 +58,6 @@ - +