| |
| |
| |
| let SESSION_ID = localStorage.getItem('agentui_username') || ''; |
|
|
| function apiFetch(url, options = {}) { |
| if (SESSION_ID) { |
| options.headers = { ...options.headers, 'X-Session-ID': SESSION_ID }; |
| } |
| return fetch(url, options); |
| } |
|
|
| function sanitizeUsername(name) { |
| return name.trim().toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9\-]/g, '').substring(0, 30); |
| } |
|
|
| |
| |
| |
| |
| let AGENT_REGISTRY = {}; |
| |
| const VIRTUAL_TYPE_LABELS = { search: 'SEARCH', browse: 'BROWSE' }; |
|
|
| |
| function getTypeLabel(type) { |
| if (AGENT_REGISTRY[type]) return AGENT_REGISTRY[type].label; |
| if (VIRTUAL_TYPE_LABELS[type]) return VIRTUAL_TYPE_LABELS[type]; |
| return type.toUpperCase(); |
| } |
| function getPlaceholder(type) { |
| return AGENT_REGISTRY[type]?.placeholder || 'Enter message...'; |
| } |
| function getDefaultCounters() { |
| const counters = {}; |
| for (const [key, agent] of Object.entries(AGENT_REGISTRY)) { |
| if (agent.hasCounter) counters[key] = 0; |
| } |
| return counters; |
| } |
|
|
| |
| let tabCounter = 1; |
| let activeTabId = 0; |
| let currentSession = null; |
| const collapsedAgents = new Set(); |
| let researchQueryTabIds = {}; |
| let showAllTurns = true; |
|
|
| |
| async function generateSessionName() { |
| try { |
| const response = await apiFetch('/api/sessions/random-name'); |
| const data = await response.json(); |
| return data.name; |
| } catch (error) { |
| |
| return `session-${Date.now()}`; |
| } |
| } |
|
|
| let settings = { |
| |
| providers: {}, |
| models: {}, |
| agents: {}, |
| |
| e2bKey: '', |
| serperKey: '', |
| hfToken: '', |
| |
| imageGenModel: '', |
| imageEditModel: '', |
| |
| researchSubAgentModel: '', |
| researchParallelWorkers: null, |
| researchMaxWebsites: null, |
| |
| themeColor: 'forest', |
| |
| settingsVersion: 2 |
| }; |
|
|
| |
| const actionWidgets = {}; |
|
|
| |
| const toolCallIds = {}; |
|
|
| |
| |
| const globalFigureRegistry = {}; |
|
|
| |
| |
| const debugHistory = {}; |
|
|
| |
| const taskIdToTabId = {}; |
|
|
| |
| let commandInputBlocked = false; |
|
|
| |
| let pendingAgentLaunches = 0; |
|
|
| |
| let agentCounters = getDefaultCounters(); |
|
|
| |
| let saveWorkspaceTimer = null; |
|
|
| |
| const activeAbortControllers = {}; |
|
|
| |
| |
| const timelineData = { |
| 0: { type: 'command', title: 'Task Center', events: [], parentTabId: null, isGenerating: false } |
| }; |
|
|
| |
| function resetLocalState() { |
| |
| tabCounter = 1; |
| activeTabId = 0; |
| currentSession = null; |
| collapsedAgents.clear(); |
|
|
| |
| Object.keys(actionWidgets).forEach(k => delete actionWidgets[k]); |
| Object.keys(toolCallIds).forEach(k => delete toolCallIds[k]); |
| Object.keys(globalFigureRegistry).forEach(k => delete globalFigureRegistry[k]); |
| Object.keys(debugHistory).forEach(k => delete debugHistory[k]); |
| Object.keys(taskIdToTabId).forEach(k => delete taskIdToTabId[k]); |
| researchQueryTabIds = {}; |
| showAllTurns = true; |
| agentCounters = getDefaultCounters(); |
|
|
| |
| const compactCb = document.getElementById('compactViewCheckbox'); |
| if (compactCb) compactCb.checked = false; |
| const collapseAgentsCb = document.getElementById('collapseAgentsCheckbox'); |
| if (collapseAgentsCb) collapseAgentsCb.checked = false; |
| const collapseToolsCb = document.getElementById('collapseToolsCheckbox'); |
| if (collapseToolsCb) collapseToolsCb.checked = false; |
|
|
| |
| Object.keys(timelineData).forEach(k => delete timelineData[k]); |
| timelineData[0] = { type: 'command', title: 'Task Center', events: [], parentTabId: null, isGenerating: false }; |
|
|
| |
| const dynamicTabs = document.getElementById('dynamicTabs'); |
| if (dynamicTabs) dynamicTabs.innerHTML = ''; |
|
|
| |
| document.querySelectorAll('.tab-content').forEach(el => { |
| if (el.dataset.contentId !== '0') el.remove(); |
| }); |
|
|
| |
| const commandMessages = document.getElementById('messages-command'); |
| if (commandMessages) commandMessages.innerHTML = ''; |
|
|
| |
| closeAllPanels(); |
| } |
|
|
| function escapeHtml(text) { |
| const div = document.createElement('div'); |
| div.textContent = text; |
| return div.innerHTML; |
| } |
|
|
| function formatDate(timestamp) { |
| const date = new Date(timestamp * 1000); |
| const now = new Date(); |
| const diff = now - date; |
|
|
| if (diff < 60000) return 'just now'; |
| if (diff < 3600000) return Math.floor(diff / 60000) + 'm ago'; |
| if (diff < 86400000) return Math.floor(diff / 3600000) + 'h ago'; |
| if (diff < 604800000) return Math.floor(diff / 86400000) + 'd ago'; |
|
|
| return date.toLocaleDateString(); |
| } |
|
|
| |
| |
| |
|
|
| |
| function setupInputListeners(container, tabId) { |
| const input = container.querySelector('textarea'); |
| const sendBtn = container.querySelector('.input-container button'); |
| if (!input || !sendBtn) return; |
|
|
| sendBtn.addEventListener('click', () => sendMessage(tabId)); |
|
|
| input.addEventListener('input', () => { |
| input.style.height = 'auto'; |
| input.style.height = Math.min(input.scrollHeight, 200) + 'px'; |
| input.style.overflowY = input.scrollHeight > 200 ? 'auto' : 'hidden'; |
| }); |
|
|
| input.addEventListener('keydown', (e) => { |
| if (e.key === 'Enter' && !e.shiftKey) { |
| e.preventDefault(); |
| sendMessage(tabId); |
| } |
| }); |
| } |
|
|
| |
| function setupCollapseToggle(cell, labelSelector) { |
| const label = cell.querySelector(labelSelector || '.tool-cell-label, .code-cell-label'); |
| if (!label) return; |
| label.addEventListener('click', () => { |
| cell.classList.toggle('collapsed'); |
| const toggle = cell.querySelector('.widget-collapse-toggle'); |
| if (toggle) toggle.classList.toggle('collapsed'); |
| }); |
| } |
|
|
| |
| function closeAllPanels() { |
| const app = document.querySelector('.app-container'); |
| for (const [panelId, btnId, cls] of [ |
| ['settingsPanel', 'settingsBtn', 'panel-open'], |
| ['debugPanel', 'debugBtn', 'panel-open'], |
| ['filesPanel', 'filesBtn', 'files-panel-open'], |
| ['sessionsPanel', 'sessionsBtn', 'sessions-panel-open'], |
| ]) { |
| document.getElementById(panelId)?.classList.remove('active'); |
| document.getElementById(btnId)?.classList.remove('active'); |
| if (cls && app) app.classList.remove(cls); |
| } |
| } |
|
|