Spaces:
Running
Running
| // ============================================ | |
| // 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 = '<option value="">-- Select session --</option>'; | |
| 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 = '<div class="sessions-loading">No other sessions</div>'; | |
| 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 = ` | |
| <span class="sessions-list-item-name">${escapeHtml(session.name)}</span> | |
| <span class="sessions-list-item-date">${formatDate(session.modified)}</span> | |
| ${!isCurrent ? `<button class="sessions-delete-btn" title="Delete session">×</button>` : ''} | |
| `; | |
| 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 = '<option value="">-- Select session --</option>'; | |
| 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(); | |
| } | |
| } | |
| }); | |
| } | |
| } | |