| |
| |
| |
|
|
| 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'); |
|
|
| |
| 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'; |
|
|
| |
| 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'); |
|
|
| |
| 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(); |
|
|
| |
| const nameEl = document.getElementById('currentSessionName'); |
| if (nameEl) nameEl.textContent = sessionName; |
|
|
| const renameInput = document.getElementById('currentSessionRename'); |
| if (renameInput) renameInput.value = sessionName; |
|
|
| |
| if (timelineData[0]) { |
| timelineData[0].title = sessionName; |
| renderTimeline(); |
| } |
|
|
| |
| await loadWorkspace(); |
|
|
| |
| 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) { |
| |
| 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; |
|
|
| |
| const nameEl = document.getElementById('currentSessionName'); |
| if (nameEl) nameEl.textContent = data.name; |
|
|
| |
| 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'); |
|
|
| |
| 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) { |
| |
| item.querySelector('.sessions-list-item-name').addEventListener('click', () => selectSession(session.name)); |
| item.querySelector('.sessions-list-item-date').addEventListener('click', () => selectSession(session.name)); |
|
|
| |
| 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; |
| } |
|
|
| |
| refreshSessionsList(); |
|
|
| |
| 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() { |
| |
| const createBtn = document.getElementById('createSessionBtn'); |
| const newNameInput = document.getElementById('newSessionName'); |
| const existingSelect = document.getElementById('existingSessionSelect'); |
|
|
| |
| if (newNameInput) { |
| generateSessionName().then(name => newNameInput.value = name); |
| } |
|
|
| |
| 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 { |
| |
| 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); |
| } |
| }); |
| } |
|
|
| |
|
|
| |
| 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); |
| } |
| }); |
| } |
|
|
| |
| const panelCreateBtn = document.getElementById('panelCreateSessionBtn'); |
| const panelNewNameInput = document.getElementById('panelNewSessionName'); |
| const panelRegenerateBtn = document.getElementById('panelRegenerateNameBtn'); |
|
|
| |
| if (panelNewNameInput) { |
| generateSessionName().then(name => panelNewNameInput.value = name); |
| } |
|
|
| |
| 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); |
| |
| if (panelNewNameInput) { |
| panelNewNameInput.value = await generateSessionName(); |
| } |
| } |
| }); |
| } |
| } |
|
|