// Claude Code IDE JavaScript let currentSession = null; let currentProjectName = null; let ws = null; // Streaming message state for accumulating response chunks // MUST be declared at module scope BEFORE any functions that use them let streamingMessageElement = null; let streamingMessageContent = ''; let streamingTimeout = null; // ============================================================ // REAL-TIME LOGGER WITH AUTO-FIX // ============================================================ // Tier 1: Client-side auto-fix (instant) // Tier 2: Escalation to AI agents (systematic-debugging + brainstorming) window.AutoFixLogger = (function() { const logs = []; const maxLogs = 100; let panel = null; // Create the logger panel function createPanel() { if (panel) return; panel = document.createElement('div'); panel.id = 'autofix-logger-panel'; panel.innerHTML = `
No active sessions
'; } // Update projects list - CLEAR LOADING STATE const projectsEl = document.getElementById('recent-projects-list'); if (projectsData.projects && projectsData.projects.length > 0) { projectsEl.innerHTML = projectsData.projects.slice(0, 5).map(project => `No projects yet
'; } } catch (error) { console.error('Error loading dashboard:', error); // Clear loading states on error const activeSessionsEl = document.getElementById('active-sessions-list'); const projectsEl = document.getElementById('recent-projects-list'); if (activeSessionsEl) activeSessionsEl.innerHTML = 'Error loading sessions
'; if (projectsEl) projectsEl.innerHTML = 'Error loading projects
'; } } function refreshSessions() { loadDashboard(); } // Sessions async function loadSessions() { const sessionsListEl = document.getElementById('sessions-list'); try { // Get current project from URL const urlParams = new URLSearchParams(window.location.search); const projectPath = urlParams.get('project'); // Build API URL with project filter let apiUrl = '/claude/api/claude/sessions'; if (projectPath) { apiUrl += `?project=${encodeURIComponent(projectPath)}`; console.log('[Sessions] Loading sessions for project:', projectPath); } // Show loading state sessionsListEl.innerHTML = 'β οΈ Session expired
No sessions found for ${escapeHtml(projectName)}
Failed to load sessions
The session ${escapeHtml(sessionId)} could not be found.
No output yet
'} ${session.outputBuffer?.length > 50 ? `...and ${session.outputBuffer.length - 50} more entries
` : ''}Select another session from the sidebar
Click to view project details
No projects yet. Create your first project!
'; } } catch (error) { console.error('Error loading projects:', error); } } async function viewProject(projectName) { // Open the project file in the files view const path = `Claude Projects/${projectName}.md`; loadFileContent(path); switchView('files'); } // Files async function loadFiles() { try { const res = await fetchWithTimeout('/claude/api/files', 5000); const data = await res.json(); const treeEl = document.getElementById('file-tree'); treeEl.innerHTML = renderFileTree(data.tree); } catch (error) { console.error('Error loading files:', error); } } async function loadTerminal() { // Initialize terminal manager if not already done if (!window.terminalManager) { window.terminalManager = new TerminalManager(); await window.terminalManager.initialize(); } // Set up new terminal button const btnNewTerminal = document.getElementById('btn-new-terminal'); if (btnNewTerminal) { btnNewTerminal.onclick = () => { window.terminalManager.createTerminal(); }; } } function renderFileTree(tree, level = 0) { return tree.map(item => { const padding = level * 1 + 0.5; const icon = item.type === 'folder' ? 'π' : 'π'; if (item.type === 'folder' && item.children) { return `${escapeHtml(data.content || '')}
${escapeHtml(data.content || '')}
${error.message}
${escapeHtml(message)}
`; document.body.appendChild(overlay); } else { // Update message if provided const textElement = overlay.querySelector('.loading-text'); if (textElement) { textElement.textContent = message; } } overlay.classList.remove('hidden'); setTimeout(() => { overlay.classList.add('visible'); }, 10); } /** * Hide loading overlay */ function hideLoadingOverlay() { const overlay = document.getElementById('loading-overlay'); if (overlay) { overlay.classList.remove('visible'); setTimeout(() => { overlay.classList.add('hidden'); }, 300); } } /** * Show toast notification * @param {string} message - The message to display * @param {string} type - The type of toast: 'success', 'error', 'info' * @param {number} duration - Duration in milliseconds (default: 3000) */ function showToast(message, type = 'info', duration = 3000) { // Remove existing toasts const existingToasts = document.querySelectorAll('.toast-notification'); existingToasts.forEach(toast => toast.remove()); // Create toast element const toast = document.createElement('div'); toast.className = `toast-notification toast-${type}`; toast.innerHTML = ` `; document.body.appendChild(toast); // Trigger animation setTimeout(() => { toast.classList.add('visible'); }, 10); // Auto remove after duration setTimeout(() => { toast.classList.remove('visible'); setTimeout(() => { toast.remove(); }, 300); }, duration); } /** * Get toast icon based on type */ function getToastIcon(type) { const icons = { success: 'β', error: 'β', info: 'βΉ', warning: 'β ' }; return icons[type] || icons.info; } /** * Fetch with timeout protection to prevent hanging requests * @param {string} url - The URL to fetch * @param {number} timeout - Timeout in milliseconds * @param {object} options - Fetch options * @returns {Promise