/** * AnyCoder - AI Code Generator * Main application logic for browser-based code generation using Transformers.js */ // DOM Elements const promptInput = document.getElementById('prompt'); const languageSelect = document.getElementById('language'); const generateBtn = document.getElementById('generate-btn'); const loadingSection = document.getElementById('loading-section'); const progressBar = document.getElementById('progress-bar'); const loadingText = document.getElementById('loading-text'); const loadingSubtext = document.getElementById('loading-subtext'); const errorSection = document.getElementById('error-section'); const errorText = document.getElementById('error-text'); const dismissErrorBtn = document.getElementById('dismiss-error'); const outputSection = document.getElementById('output-section'); const generatedCodeElement = document.getElementById('generated-code'); const copyBtn = document.getElementById('copy-btn'); const modelInfo = document.getElementById('model-info'); // Application state let isModelLoaded = false; let isGenerating = false; let worker = null; // Initialize the application function init() { // Check for HTTPS requirement if (window.location.protocol === 'http:' && window.location.hostname !== 'localhost') { showError('This application requires HTTPS for full functionality. Please use a secure connection.'); return; } // Create and setup Web Worker try { worker = new Worker('worker.js', { type: 'module' }); } catch (error) { console.error('Failed to create worker:', error); showError('Failed to initialize worker. Please ensure the site is served over HTTP/HTTPS (not file://).'); return; } // Listen for messages from worker worker.onmessage = handleWorkerMessage; worker.onerror = (error) => { console.error('Worker error:', error); showError(`Worker error: ${error.message || 'Unknown error'}. Check console for details.`); }; // Setup event listeners generateBtn.addEventListener('click', handleGenerate); copyBtn.addEventListener('click', handleCopy); dismissErrorBtn.addEventListener('click', hideError); promptInput.addEventListener('keydown', (e) => { if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) { e.preventDefault(); handleGenerate(); } }); // Show model info modelInfo.style.display = 'block'; // Load model on page load loadModel(); } // Handle messages from Web Worker function handleWorkerMessage(event) { const { type, data } = event.data; switch (type) { case 'progress': updateProgress(data); break; case 'modelLoaded': onModelLoaded(); break; case 'generationComplete': onGenerationComplete(data); break; case 'error': onError(data); break; default: console.warn('Unknown message type from worker:', type); } } // Load the model function loadModel() { loadingSection.style.display = 'block'; loadingText.textContent = 'Initializing model...'; loadingSubtext.textContent = 'This may take several minutes on first load'; // Send load command to worker worker.postMessage({ type: 'loadModel' }); } // Update progress bar function updateProgress(progress) { const percent = Math.round(progress * 100); progressBar.style.width = `${percent}%`; loadingText.textContent = `Loading model... ${percent}%`; if (percent > 50) { loadingSubtext.textContent = 'Almost there...'; } } // Called when model is loaded function onModelLoaded() { isModelLoaded = true; loadingSection.style.display = 'none'; progressBar.style.width = '0%'; generateBtn.disabled = false; generateBtn.querySelector('.btn-text').textContent = 'Generate Code'; modelInfo.style.display = 'none'; console.log('Model loaded successfully'); } // Handle generate button click async function handleGenerate() { const prompt = promptInput.value.trim(); if (!prompt) { showError('Please enter a description of what you want to generate.'); return; } if (!isModelLoaded) { showError('Model is still loading. Please wait...'); return; } if (isGenerating) { return; } // Clear previous errors and output hideError(); outputSection.style.display = 'none'; // Update UI state isGenerating = true; generateBtn.disabled = true; generateBtn.querySelector('.btn-text').textContent = 'Generating...'; generateBtn.querySelector('.btn-spinner').style.display = 'block'; // Prepare the prompt with language context const language = languageSelect.value; const enhancedPrompt = `Generate ${language} code: ${prompt}\n\n\`\`\`${language}\n`; // Send generation request to worker worker.postMessage({ type: 'generate', data: { prompt: enhancedPrompt, language } }); } // Called when generation is complete function onGenerationComplete(result) { const { generatedText, language } = result; // Extract code between code fences if present let code = extractCodeFromResponse(generatedText, language); // Update the UI displayGeneratedCode(code, language); // Reset UI state resetUIState(); } // Extract code from model response function extractCodeFromResponse(generatedText, language) { // Try to extract code between fences first const codeFenceMatch = generatedText.match(/```(?:\w+)?\n([\s\S]*?)```/); if (codeFenceMatch) { return codeFenceMatch[1].trim(); } // If no fences, try to extract code after the prompt const promptMarker = `Generate ${language} code:`; const promptIndex = generatedText.indexOf(promptMarker); if (promptIndex !== -1) { let code = generatedText.substring(promptIndex + promptMarker.length).trim(); // Remove common prefixes code = code.replace(/^(Here is|This is|Below is|Here's)\s+(the\s+)?(code|example|function)/i, '').trim(); // Clean up trailing text const lines = code.split('\n'); const codeLines = []; for (let line of lines) { const trimmed = line.trim(); // Stop at common explanation markers if (trimmed.match(/^(Here is|This code|Explanation:|Note:|The code|This function)/i)) { break; } codeLines.push(line); } return codeLines.join('\n').trim(); } return generatedText.trim(); } // Display generated code with syntax highlighting function displayGeneratedCode(code, language) { // Set the code content generatedCodeElement.textContent = code; // Update language class generatedCodeElement.className = `language-${getPrismLanguage(language)}`; // Highlight the code if (typeof Prism !== 'undefined') { Prism.highlightElement(generatedCodeElement); } // Show output section outputSection.style.display = 'block'; // Scroll to output setTimeout(() => { outputSection.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }, 100); } // Get Prism.js language identifier function getPrismLanguage(language) { const languageMap = { 'javascript': 'javascript', 'python': 'python', 'html': 'markup', 'react': 'jsx', 'sql': 'sql', 'bash': 'bash', 'other': 'javascript' }; return languageMap[language] || 'javascript'; } // Handle copy button click async function handleCopy() { const code = generatedCodeElement.textContent; try { await navigator.clipboard.writeText(code); const originalText = copyBtn.textContent; copyBtn.textContent = 'Copied!'; copyBtn.style.backgroundColor = 'var(--accent-success)'; setTimeout(() => { copyBtn.textContent = originalText; copyBtn.style.backgroundColor = ''; }, 2000); } catch (err) { console.error('Failed to copy code:', err); showError('Failed to copy code to clipboard'); } } // Show error message function showError(message) { errorText.textContent = message; errorSection.style.display = 'block'; } // Hide error message function hideError() { errorSection.style.display = 'none'; } // Reset UI state after generation function resetUIState() { isGenerating = false; generateBtn.disabled = false; generateBtn.querySelector('.btn-text').textContent = 'Generate Code'; generateBtn.querySelector('.btn-spinner').style.display = 'none'; } // Handle errors from worker function onError(error) { console.error('Worker error:', error); showError(`An error occurred: ${error.message || 'Unknown error'}. Please check the console and try again.`); resetUIState(); } // Initialize the app when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } // Handle page unload to terminate worker window.addEventListener('beforeunload', () => { if (worker) { worker.terminate(); } });