Spaces:
Paused
Paused
dr-data
Fix preview component: eliminate blinking, ensure HTML updates, add smooth transitions
dcd5e1d
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AI Debug Test</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| max-width: 800px; | |
| margin: 50px auto; | |
| padding: 20px; | |
| background: #f5f5f5; | |
| } | |
| .container { | |
| background: white; | |
| padding: 30px; | |
| border-radius: 10px; | |
| box-shadow: 0 2px 10px rgba(0,0,0,0.1); | |
| } | |
| .form-group { | |
| margin-bottom: 20px; | |
| } | |
| label { | |
| display: block; | |
| margin-bottom: 5px; | |
| font-weight: bold; | |
| } | |
| input, select, textarea { | |
| width: 100%; | |
| padding: 10px; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| font-size: 14px; | |
| } | |
| button { | |
| background: #007bff; | |
| color: white; | |
| padding: 12px 24px; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| font-size: 16px; | |
| } | |
| button:hover { | |
| background: #0056b3; | |
| } | |
| button:disabled { | |
| background: #ccc; | |
| cursor: not-allowed; | |
| } | |
| .output { | |
| margin-top: 20px; | |
| padding: 15px; | |
| background: #f8f9fa; | |
| border-radius: 5px; | |
| border-left: 4px solid #007bff; | |
| white-space: pre-wrap; | |
| font-family: monospace; | |
| max-height: 400px; | |
| overflow-y: auto; | |
| } | |
| .error { | |
| border-left-color: #dc3545; | |
| background: #f8d7da; | |
| color: #721c24; | |
| } | |
| .status { | |
| margin-top: 10px; | |
| padding: 10px; | |
| border-radius: 5px; | |
| font-weight: bold; | |
| } | |
| .status.thinking { background: #fff3cd; color: #856404; } | |
| .status.success { background: #d4edda; color: #155724; } | |
| .status.error { background: #f8d7da; color: #721c24; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>π§ AI Debug Test Tool</h1> | |
| <p>This tool helps debug the "AI is thinking" issue by testing the API directly.</p> | |
| <form id="testForm"> | |
| <div class="form-group"> | |
| <label for="provider">Provider:</label> | |
| <select id="provider" name="provider"> | |
| <option value="auto">HuggingFace (Auto)</option> | |
| <option value="openrouter">OpenRouter</option> | |
| </select> | |
| </div> | |
| <div class="form-group"> | |
| <label for="model">Model:</label> | |
| <select id="model" name="model"> | |
| <option value="Qwen/Qwen2.5-Coder-32B-Instruct">Qwen 2.5 Coder 32B</option> | |
| <option value="meta-llama/Llama-3.2-3B-Instruct">Llama 3.2 3B</option> | |
| </select> | |
| </div> | |
| <div class="form-group" id="apiKeyGroup" style="display: none;"> | |
| <label for="apiKey">OpenRouter API Key:</label> | |
| <input type="password" id="apiKey" name="apiKey" placeholder="sk-or-..."> | |
| </div> | |
| <div class="form-group"> | |
| <label for="prompt">Prompt:</label> | |
| <textarea id="prompt" name="prompt" rows="3" placeholder="Create a simple landing page">Create a simple landing page with a header, hero section, and footer</textarea> | |
| </div> | |
| <button type="submit" id="submitBtn">Test AI Request</button> | |
| <button type="button" id="stopBtn" style="display: none; background: #dc3545;">Stop Request</button> | |
| </form> | |
| <div id="status"></div> | |
| <div id="output"></div> | |
| </div> | |
| <script> | |
| let controller = null; | |
| let chunkCount = 0; | |
| let responseLength = 0; | |
| const form = document.getElementById('testForm'); | |
| const providerSelect = document.getElementById('provider'); | |
| const modelSelect = document.getElementById('model'); | |
| const apiKeyGroup = document.getElementById('apiKeyGroup'); | |
| const submitBtn = document.getElementById('submitBtn'); | |
| const stopBtn = document.getElementById('stopBtn'); | |
| const statusDiv = document.getElementById('status'); | |
| const outputDiv = document.getElementById('output'); | |
| // Update UI based on provider selection | |
| providerSelect.addEventListener('change', function() { | |
| const isOpenRouter = this.value === 'openrouter'; | |
| apiKeyGroup.style.display = isOpenRouter ? 'block' : 'none'; | |
| // Update model options | |
| if (isOpenRouter) { | |
| modelSelect.innerHTML = ` | |
| <option value="anthropic/claude-3.5-sonnet">Claude 3.5 Sonnet</option> | |
| <option value="openai/gpt-4o">GPT-4o</option> | |
| <option value="meta-llama/llama-3.1-8b-instruct">Llama 3.1 8B</option> | |
| `; | |
| } else { | |
| modelSelect.innerHTML = ` | |
| <option value="Qwen/Qwen2.5-Coder-32B-Instruct">Qwen 2.5 Coder 32B</option> | |
| <option value="meta-llama/Llama-3.2-3B-Instruct">Llama 3.2 3B</option> | |
| `; | |
| } | |
| }); | |
| function showStatus(message, type = 'thinking') { | |
| statusDiv.innerHTML = `<div class="status ${type}">${message}</div>`; | |
| } | |
| function showOutput(content, isError = false) { | |
| outputDiv.innerHTML = `<div class="output ${isError ? 'error' : ''}">${content}</div>`; | |
| } | |
| function appendOutput(content) { | |
| if (!outputDiv.querySelector('.output')) { | |
| showOutput(''); | |
| } | |
| outputDiv.querySelector('.output').textContent += content; | |
| } | |
| form.addEventListener('submit', async function(e) { | |
| e.preventDefault(); | |
| const formData = new FormData(form); | |
| const provider = formData.get('provider'); | |
| const model = formData.get('model'); | |
| const prompt = formData.get('prompt'); | |
| const apiKey = formData.get('apiKey'); | |
| if (provider === 'openrouter' && !apiKey) { | |
| showStatus('β OpenRouter API key is required', 'error'); | |
| return; | |
| } | |
| if (!prompt.trim()) { | |
| showStatus('β Prompt is required', 'error'); | |
| return; | |
| } | |
| // Reset state | |
| chunkCount = 0; | |
| responseLength = 0; | |
| controller = new AbortController(); | |
| submitBtn.disabled = true; | |
| submitBtn.textContent = 'Testing...'; | |
| stopBtn.style.display = 'inline-block'; | |
| showStatus('π Starting AI request...', 'thinking'); | |
| showOutput(''); | |
| try { | |
| console.log('π Sending request:', { provider, model, promptLength: prompt.length }); | |
| const response = await fetch('/api/ask-ai', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| prompt, | |
| provider, | |
| model, | |
| html: '', | |
| openrouterApiKey: apiKey | |
| }), | |
| signal: controller.signal | |
| }); | |
| console.log('π₯ Response received:', response.status, response.statusText); | |
| showStatus(`π₯ Response: ${response.status} ${response.statusText}`, 'thinking'); | |
| if (!response.ok) { | |
| const errorData = await response.json(); | |
| throw new Error(`HTTP ${response.status}: ${errorData.message || response.statusText}`); | |
| } | |
| if (!response.body) { | |
| throw new Error('No response body received'); | |
| } | |
| showStatus('π Processing stream...', 'thinking'); | |
| const reader = response.body.getReader(); | |
| const decoder = new TextDecoder(); | |
| let buffer = ''; | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) { | |
| console.log('β Stream completed:', { chunkCount, responseLength }); | |
| showStatus(`β Completed! Chunks: ${chunkCount}, Length: ${responseLength}`, 'success'); | |
| break; | |
| } | |
| const chunk = decoder.decode(value, { stream: true }); | |
| chunkCount++; | |
| responseLength += chunk.length; | |
| buffer += chunk; | |
| console.log(`π¦ Chunk ${chunkCount}:`, { | |
| length: chunk.length, | |
| totalLength: responseLength, | |
| preview: chunk.substring(0, 100) + (chunk.length > 100 ? '...' : '') | |
| }); | |
| showStatus(`π Chunk ${chunkCount}, Total: ${responseLength} chars`, 'thinking'); | |
| // Try to parse as JSON (error case) | |
| try { | |
| const errorData = JSON.parse(chunk); | |
| showOutput(`Error: ${JSON.stringify(errorData, null, 2)}`, true); | |
| showStatus('β Error received', 'error'); | |
| break; | |
| } catch { | |
| // Not JSON, normal content | |
| appendOutput(chunk); | |
| // Check if we have HTML starting | |
| if (buffer.includes('<!DOCTYPE html>')) { | |
| showStatus(`π HTML detected! Chunk ${chunkCount}, Length: ${responseLength}`, 'success'); | |
| } | |
| } | |
| } | |
| } catch (error) { | |
| console.error('β Request failed:', error); | |
| showStatus(`β Error: ${error.message}`, 'error'); | |
| showOutput(`Error: ${error.message}\n\nStack: ${error.stack}`, true); | |
| } finally { | |
| submitBtn.disabled = false; | |
| submitBtn.textContent = 'Test AI Request'; | |
| stopBtn.style.display = 'none'; | |
| controller = null; | |
| } | |
| }); | |
| stopBtn.addEventListener('click', function() { | |
| if (controller) { | |
| controller.abort(); | |
| showStatus('β Request stopped by user', 'error'); | |
| } | |
| }); | |
| // Initialize | |
| providerSelect.dispatchEvent(new Event('change')); | |
| </script> | |
| </body> | |
| </html> | |