// ============================================ // Session Management // ============================================ async function fetchSessions() { try { const response = await apiFetch('/api/sessions'); if (response.ok) { return await response.json(); } } catch (e) { console.error('Failed to fetch sessions:', e); } return { sessions: [], current: null }; } function showSessionSelector(sessions) { const selector = document.getElementById('sessionSelector'); const welcome = document.getElementById('welcomeMessage'); const sessionIndicator = document.getElementById('sessionIndicator'); const inputArea = document.getElementById('commandInputArea'); // Show welcome message and session selector, hide sidebar if (welcome) welcome.style.display = 'block'; if (selector) selector.style.display = 'block'; if (sessionIndicator) sessionIndicator.style.display = 'none'; if (inputArea) inputArea.style.display = 'none'; const sidebar = document.getElementById('agentsSidebar'); if (sidebar) sidebar.style.display = 'none'; // Populate existing sessions dropdown const select = document.getElementById('existingSessionSelect'); if (select) { select.innerHTML = ''; sessions.forEach(session => { const option = document.createElement('option'); option.value = session.name; option.textContent = `${session.name} (${formatDate(session.modified)})`; select.appendChild(option); }); } } function hideSessionSelector() { const selector = document.getElementById('sessionSelector'); const welcome = document.getElementById('welcomeMessage'); const sessionIndicator = document.getElementById('sessionIndicator'); const inputArea = document.getElementById('commandInputArea'); // Hide session selector, show session indicator, input, and sidebar if (selector) selector.style.display = 'none'; if (welcome) welcome.style.display = 'block'; if (sessionIndicator) sessionIndicator.style.display = 'block'; if (inputArea) inputArea.style.display = 'block'; const sidebar = document.getElementById('agentsSidebar'); if (sidebar) sidebar.style.display = ''; } async function onSessionSelected(sessionName) { currentSession = sessionName; hideSessionSelector(); // Update session name display const nameEl = document.getElementById('currentSessionName'); if (nameEl) nameEl.textContent = sessionName; const renameInput = document.getElementById('currentSessionRename'); if (renameInput) renameInput.value = sessionName; // Update timeline title to show session name if (timelineData[0]) { timelineData[0].title = sessionName; renderTimeline(); } // Load workspace for this session await loadWorkspace(); // Refresh sessions panel list await refreshSessionsList(); } async function createSession(name) { try { const response = await apiFetch('/api/sessions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name }) }); if (response.ok) { const data = await response.json(); await onSessionSelected(data.name); return true; } else { const error = await response.json(); alert(error.detail || 'Failed to create session'); } } catch (e) { console.error('Failed to create session:', e); alert('Failed to create session'); } return false; } async function selectSession(name) { try { const response = await apiFetch('/api/sessions/select', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name }) }); if (response.ok) { // Reset local state and load the selected session resetLocalState(); await onSessionSelected(name); return true; } else { const error = await response.json(); alert(error.detail || 'Failed to select session'); } } catch (e) { console.error('Failed to select session:', e); alert('Failed to select session'); } return false; } async function renameSession(oldName, newName) { try { const response = await apiFetch('/api/sessions/rename', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ oldName, newName }) }); if (response.ok) { const data = await response.json(); currentSession = data.name; // Update displays const nameEl = document.getElementById('currentSessionName'); if (nameEl) nameEl.textContent = data.name; // Update timeline title if (timelineData[0]) { timelineData[0].title = data.name; renderTimeline(); } await refreshSessionsList(); return true; } else { const error = await response.json(); alert(error.detail || 'Failed to rename session'); } } catch (e) { console.error('Failed to rename session:', e); alert('Failed to rename session'); } return false; } function openSessionsPanel() { const sessionsBtn = document.getElementById('sessionsBtn'); if (sessionsBtn) { sessionsBtn.click(); } } async function refreshSessionsList() { const sessionsData = await fetchSessions(); const listEl = document.getElementById('sessionsList'); // Update the current session rename input const renameInput = document.getElementById('currentSessionRename'); if (renameInput && currentSession) { renameInput.value = currentSession; } if (!listEl) return; if (sessionsData.sessions.length === 0) { listEl.innerHTML = '
No other sessions
'; return; } listEl.innerHTML = ''; sessionsData.sessions.forEach(session => { const item = document.createElement('div'); item.className = 'sessions-list-item' + (session.name === currentSession ? ' current' : ''); const isCurrent = session.name === currentSession; item.innerHTML = ` ${escapeHtml(session.name)} ${formatDate(session.modified)} ${!isCurrent ? `` : ''} `; if (!isCurrent) { // Click on name/date to select item.querySelector('.sessions-list-item-name').addEventListener('click', () => selectSession(session.name)); item.querySelector('.sessions-list-item-date').addEventListener('click', () => selectSession(session.name)); // Click on delete button to delete const deleteBtn = item.querySelector('.sessions-delete-btn'); if (deleteBtn) { deleteBtn.addEventListener('click', (e) => { e.stopPropagation(); deleteSession(session.name); }); } } listEl.appendChild(item); }); } async function deleteSession(sessionName) { if (!confirm(`Delete session "${sessionName}"? This cannot be undone.`)) { return; } try { const response = await apiFetch(`/api/sessions/${encodeURIComponent(sessionName)}`, { method: 'DELETE' }); if (!response.ok) { try { const error = await response.json(); alert(error.detail || 'Failed to delete session'); } catch { alert('Failed to delete session'); } return; } // Refresh the sessions list in the panel refreshSessionsList(); // Also refresh the welcome page dropdown const sessionsData = await fetchSessions(); const select = document.getElementById('existingSessionSelect'); if (select) { select.innerHTML = ''; sessionsData.sessions.forEach(session => { const option = document.createElement('option'); option.value = session.name; option.textContent = `${session.name} (${formatDate(session.modified)})`; select.appendChild(option); }); } } catch (error) { console.error('Error deleting session:', error); alert('Failed to delete session'); } } function initializeSessionListeners() { // Welcome page session selector const createBtn = document.getElementById('createSessionBtn'); const newNameInput = document.getElementById('newSessionName'); const existingSelect = document.getElementById('existingSessionSelect'); // Pre-populate with a cool random name if (newNameInput) { generateSessionName().then(name => newNameInput.value = name); } // Regenerate button const regenerateBtn = document.getElementById('regenerateNameBtn'); if (regenerateBtn && newNameInput) { regenerateBtn.addEventListener('click', async () => { newNameInput.value = await generateSessionName(); }); } if (createBtn) { createBtn.addEventListener('click', async () => { const name = newNameInput?.value.trim(); if (name) { createSession(name); } else { // Auto-generate name createSession(await generateSessionName()); } }); } if (newNameInput) { newNameInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') { createBtn?.click(); } }); } if (existingSelect) { existingSelect.addEventListener('change', () => { const name = existingSelect.value; if (name) { selectSession(name); } }); } // Sessions panel handlers are set up at the end of the file with other panels // Panel rename button const renameBtn = document.getElementById('renameSessionBtn'); const renameInput = document.getElementById('currentSessionRename'); if (renameBtn && renameInput) { renameBtn.addEventListener('click', () => { const newName = renameInput.value.trim(); if (newName && newName !== currentSession) { renameSession(currentSession, newName); } }); } // Panel create new session const panelCreateBtn = document.getElementById('panelCreateSessionBtn'); const panelNewNameInput = document.getElementById('panelNewSessionName'); const panelRegenerateBtn = document.getElementById('panelRegenerateNameBtn'); // Pre-populate panel input with cool name too if (panelNewNameInput) { generateSessionName().then(name => panelNewNameInput.value = name); } // Panel regenerate button if (panelRegenerateBtn && panelNewNameInput) { panelRegenerateBtn.addEventListener('click', async () => { panelNewNameInput.value = await generateSessionName(); }); } if (panelCreateBtn) { panelCreateBtn.addEventListener('click', async () => { const name = panelNewNameInput?.value.trim(); if (name) { resetLocalState(); await createSession(name); // Pre-populate a new name for next time if (panelNewNameInput) { panelNewNameInput.value = await generateSessionName(); } } }); } }