| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>AgentUI</title> |
| <link rel="icon" type="image/svg+xml" href="favicon.svg"> |
| <link rel="icon" type="image/x-icon" href="favicon.ico"> |
| <link rel="apple-touch-icon" href="apple-touch-icon.png"> |
| <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet"> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css"> |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css"> |
| <link rel="stylesheet" href="style.css?v=112"> |
| </head> |
| <body> |
| <div class="app-container"> |
| |
| <div class="tab-bar"> |
| <div class="tab active" data-tab-id="0"> |
| <span class="tab-title">MAIN</span> |
| </div> |
| <div id="dynamicTabs"></div> |
| <div class="new-tab-wrapper"> |
| <button class="new-tab-btn" id="newTabBtn">+</button> |
| <div class="new-tab-menu" id="newTabMenu"> |
| |
| </div> |
| </div> |
| <div class="tab-bar-spacer"></div> |
| <button class="sessions-btn" id="sessionsBtn">sessions</button> |
| <button class="files-btn" id="filesBtn">files</button> |
| <button class="debug-btn" id="debugBtn">debug</button> |
| <button class="settings-btn" id="settingsBtn">settings</button> |
| </div> |
|
|
| |
| <div class="content-area"> |
| |
| <div class="agents-sidebar" id="agentsSidebar"> |
| <div id="userIndicator" class="user-indicator-block" style="display:none"> |
| <span class="workspace-label">USER</span> |
| <span class="user-indicator-name" id="userIndicatorName"></span> |
| </div> |
| <div class="sidebar-content" id="sidebarAgents"> |
| |
| </div> |
| <div class="sidebar-legend"> |
| <span><span class="legend-square"></span> user</span> |
| <span><span class="legend-circle"></span> assistant</span> |
| <span><span class="legend-box"></span> agent/tool</span> |
| </div> |
| <div class="sidebar-controls"> |
| <span class="sidebar-controls-label">Timeline view:</span> |
| <label class="sidebar-checkbox"><input type="checkbox" id="compactViewCheckbox"> compact</label> |
| </div> |
| <div class="sidebar-controls"> |
| <span class="sidebar-controls-label">Chat collapse:</span> |
| <label class="sidebar-checkbox"><input type="checkbox" id="collapseAgentsCheckbox"> agents</label> |
| <label class="sidebar-checkbox"><input type="checkbox" id="collapseToolsCheckbox"> tools</label> |
| </div> |
| <div class="sidebar-resize-handle" id="sidebarResizeHandle"></div> |
| </div> |
|
|
| |
| <div class="main-content"> |
| |
| <div class="tab-content active" data-content-id="0"> |
| <div class="agent-interface"> |
| <div class="agent-header"> |
| <div> |
| <div class="agent-type">TASK CENTER</div> |
| <h2>Task Center</h2> |
| </div> |
| <div class="header-actions" id="launcherButtons"> |
| |
| <button class="debug-btn" id="debugBtn">DEBUG</button> |
| </div> |
| </div> |
|
|
| <div class="agent-body"> |
| <div class="chat-container" id="messages-command"> |
| <div class="welcome-message" id="welcomeMessage"> |
| <p>Welcome to AgentUI — an AI interface with specialized agents.</p> |
|
|
| <div class="session-selector" id="sessionSelector"> |
| <div class="session-selector-form"> |
| <div class="session-new"> |
| <label>New session:</label> |
| <div class="session-new-input"> |
| <div class="session-input-wrapper"> |
| <input type="text" id="newSessionName" placeholder="Session name..." /> |
| <button type="button" class="session-regenerate-btn" id="regenerateNameBtn" title="Generate new name">↻</button> |
| </div> |
| <button id="createSessionBtn">START</button> |
| </div> |
| </div> |
|
|
| <div class="session-existing"> |
| <label>Or continue:</label> |
| <select id="existingSessionSelect"> |
| <option value="">-- Select session --</option> |
| </select> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="welcome-explanation"> |
| <p>The assistant can automatically open specialized agents for different tasks:</p> |
| <ul> |
| <li><strong style="color: var(--theme-accent)">BASE</strong> — Basic tasks with search</li> |
| <li><strong style="color: var(--theme-accent)">CODE</strong> — Programming and data analysis</li> |
| <li><strong style="color: var(--theme-accent)">RESEARCH</strong> — Deep research and information gathering</li> |
| <li><strong style="color: var(--theme-accent)">IMAGE</strong> — Image generation and editing</li> |
| <li><strong style="color: var(--theme-accent)">COMPUTER</strong> <em>(coming soon)</em> — Computer control and automation</li> |
| </ul> |
| <div class="welcome-diagram"> |
| <div class="tl-widget compact"> |
| <div class="workspace-block"> |
| <div class="workspace-label">Agent</div> |
| <div class="workspace-name">Main agent</div> |
| </div> |
| <div class="tl"> |
| |
| <div class="tl-row turn user"><div class="tl-dot"></div><span class="tl-label">User query</span></div> |
| |
| <div class="tl-row turn"><div class="tl-dot"></div><span class="tl-label">Routing to sub-agents...</span></div> |
|
|
| |
| <div class="tl-row has-agent has-nested"> |
| <div class="tl-dot"></div> |
| <div class="agent-box"> |
| <div class="agent-header"><div class="collapse-toggle"></div><span>Research</span></div> |
| <div class="agent-body"> |
| <span class="agent-body-text">Sub-agent</span> |
| <div class="agent-status"><span>12 turns</span><div class="agent-done"></div></div> |
| </div> |
| </div> |
| </div> |
| <div class="tl-nested complete"> |
| <div class="tl"> |
| <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">search</span><span class="tl-tool-text">"topic overview"</span></div></div> |
| <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">read</span><span class="tl-tool-text">4 sources</span></div></div> |
| <div class="tl-row turn"><div class="tl-dot"></div><span class="tl-label">Synthesizing...</span></div> |
| <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">result</span></div></div> |
| </div> |
| </div> |
| <div class="tl-row tl-return"><div class="tl-dot"></div><div class="tl-return-connector"></div></div> |
|
|
| |
| <div class="tl-row has-agent has-nested"> |
| <div class="tl-dot"></div> |
| <div class="agent-box"> |
| <div class="agent-header"><div class="collapse-toggle"></div><span>Code</span></div> |
| <div class="agent-body"> |
| <span class="agent-body-text">Sub-agent</span> |
| <div class="agent-status"><span>4 turns</span><div class="agent-done"></div></div> |
| </div> |
| </div> |
| </div> |
| <div class="tl-nested complete"> |
| <div class="tl"> |
| <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">code</span><span class="tl-tool-text">import numpy as np</span></div></div> |
| <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">code</span><span class="tl-tool-text">plt.show()</span></div></div> |
| <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">result</span><span class="tl-tool-text">2 figures</span></div></div> |
| </div> |
| </div> |
| <div class="tl-row tl-return"><div class="tl-dot"></div><div class="tl-return-connector"></div></div> |
|
|
| |
| <div class="tl-row has-agent has-nested"> |
| <div class="tl-dot"></div> |
| <div class="agent-box"> |
| <div class="agent-header"><div class="collapse-toggle"></div><span>Image</span></div> |
| <div class="agent-body"> |
| <span class="agent-body-text">Sub-agent</span> |
| <div class="agent-status"><span>2 turns</span><div class="agent-done"></div></div> |
| </div> |
| </div> |
| </div> |
| <div class="tl-nested complete"> |
| <div class="tl"> |
| <div class="tl-row turn"><div class="tl-dot"></div><span class="tl-label">Generating image...</span></div> |
| <div class="tl-row turn"><div class="tl-dot"></div><div class="tl-tool"><span class="tl-tool-tag">result</span><span class="tl-tool-text">1 image</span></div></div> |
| </div> |
| </div> |
| <div class="tl-row tl-return"><div class="tl-dot"></div><div class="tl-return-connector"></div></div> |
|
|
| |
| <div class="tl-row turn"><div class="tl-dot"></div><span class="tl-label">Summarize results</span></div> |
| </div> |
| </div> |
| </div> |
| <p>When an agent is opened, you'll see a widget you can click to jump to it. A pulsing dot on the tab indicates active generation.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="input-area" id="commandInputArea" style="display: none;"> |
| <div class="input-container"> |
| <textarea placeholder="Enter message..." id="input-command" rows="1"></textarea> |
| <button id="sendCommand">SEND</button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="settings-panel" id="settingsPanel"> |
| <div class="settings-panel-header"> |
| <h3>SETTINGS</h3> |
| <span class="settings-path" id="settingsPath"></span> |
| <button class="settings-panel-close" id="settingsPanelClose">×</button> |
| </div> |
| <div class="settings-panel-body" id="settingsPanelBody"> |
| <div class="settings-body"> |
| |
| <div class="settings-group"> |
| <div class="settings-group-header"> |
| <div class="widget-collapse-toggle"></div> |
| <span class="settings-group-title">Agent Models</span> |
| </div> |
| <div class="settings-group-body"> |
| <div class="settings-section"> |
| <div class="agent-models-grid" id="agentModelsGrid"> |
| |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="settings-group collapsed"> |
| <div class="settings-group-header"> |
| <div class="widget-collapse-toggle collapsed"></div> |
| <span class="settings-group-title">Models & Providers</span> |
| </div> |
| <div class="settings-group-body"> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">PROVIDERS</span> |
| <span class="label-description">API endpoints for LLM services</span> |
| </label> |
| <div id="providers-list" class="settings-list"></div> |
| <button type="button" class="settings-add-btn" onclick="showProviderDialog()">+ Add Provider</button> |
| </div> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">MODELS</span> |
| <span class="label-description">Models available from your providers</span> |
| </label> |
| <div id="models-list" class="settings-list"></div> |
| <button type="button" class="settings-add-btn" onclick="showModelDialog()">+ Add Model</button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="settings-group collapsed"> |
| <div class="settings-group-header"> |
| <div class="widget-collapse-toggle collapsed"></div> |
| <span class="settings-group-title">API Keys</span> |
| </div> |
| <div class="settings-group-body"> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">E2B API KEY</span> |
| <span class="label-description">Required for code execution in CODE agents</span> |
| </label> |
| <input type="password" id="setting-e2b-key" class="settings-input" placeholder="Leave empty if not using code execution"> |
| </div> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">SERPER API KEY</span> |
| <span class="label-description">Required for web search in RESEARCH agents</span> |
| </label> |
| <input type="password" id="setting-serper-key" class="settings-input" placeholder="Leave empty if not using research"> |
| </div> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">HUGGINGFACE TOKEN</span> |
| <span class="label-description">Required for image generation in IMAGE agents</span> |
| </label> |
| <input type="password" id="setting-hf-token" class="settings-input" placeholder="Leave empty to use provider token"> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="settings-group collapsed"> |
| <div class="settings-group-header"> |
| <div class="widget-collapse-toggle collapsed"></div> |
| <span class="settings-group-title">Agent Settings</span> |
| </div> |
| <div class="settings-group-body"> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">IMAGE GENERATION MODEL</span> |
| <span class="label-description">Model for text-to-image generation</span> |
| </label> |
| <select id="setting-image-gen-model" class="settings-select"></select> |
| </div> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">IMAGE EDIT MODEL</span> |
| <span class="label-description">Model for image-to-image editing</span> |
| </label> |
| <select id="setting-image-edit-model" class="settings-select"></select> |
| </div> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">RESEARCH SUB-AGENT MODEL</span> |
| <span class="label-description">Smaller/faster model for analyzing web pages during research</span> |
| </label> |
| <select id="setting-research-sub-agent-model" class="settings-select"></select> |
| </div> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">RESEARCH PARALLEL WORKERS</span> |
| <span class="label-description">Number of web pages to analyze in parallel (default: 8)</span> |
| </label> |
| <input type="number" id="setting-research-parallel-workers" class="settings-input" placeholder="8" min="1" max="20"> |
| </div> |
| <div class="settings-section"> |
| <label class="settings-label"> |
| <span class="label-text">RESEARCH MAX WEBSITES</span> |
| <span class="label-description">Max websites to analyze per session (default: 50)</span> |
| </label> |
| <input type="number" id="setting-research-max-websites" class="settings-input" placeholder="50" min="10" max="200"> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="settings-group collapsed"> |
| <div class="settings-group-header"> |
| <div class="widget-collapse-toggle collapsed"></div> |
| <span class="settings-group-title">Theme</span> |
| </div> |
| <div class="settings-group-body"> |
| <div class="settings-section"> |
| <div class="theme-color-picker" id="theme-color-picker"> |
| <div class="theme-option" data-theme="forest"> |
| <div class="theme-preview" style="border-color: #1b5e20; background: #e8f5e9;"></div> |
| <span class="theme-name">Forest</span> |
| </div> |
| <div class="theme-option" data-theme="sapphire"> |
| <div class="theme-preview" style="border-color: #0d47a1; background: #e3f2fd;"></div> |
| <span class="theme-name">Sapphire</span> |
| </div> |
| <div class="theme-option" data-theme="ocean"> |
| <div class="theme-preview" style="border-color: #00796b; background: #e0f2f1;"></div> |
| <span class="theme-name">Ocean</span> |
| </div> |
| <div class="theme-option" data-theme="midnight"> |
| <div class="theme-preview" style="border-color: #283593; background: #e8eaf6;"></div> |
| <span class="theme-name">Midnight</span> |
| </div> |
| <div class="theme-option" data-theme="steel"> |
| <div class="theme-preview" style="border-color: #455a64; background: #eceff1;"></div> |
| <span class="theme-name">Steel</span> |
| </div> |
| <div class="theme-option" data-theme="depths"> |
| <div class="theme-preview" style="border-color: #01579b; background: #e3f2fd;"></div> |
| <span class="theme-name">Depths</span> |
| </div> |
| <div class="theme-option" data-theme="ember"> |
| <div class="theme-preview" style="border-color: #b71c1c; background: #fbe9e7;"></div> |
| <span class="theme-name">Ember</span> |
| </div> |
| <div class="theme-option" data-theme="noir"> |
| <div class="theme-preview" style="border-color: #888888; background: #111111;"></div> |
| <span class="theme-name">Noir</span> |
| </div> |
| <div class="theme-option" data-theme="eclipse"> |
| <div class="theme-preview" style="border-color: #5c9eff; background: #0b1118;"></div> |
| <span class="theme-name">Eclipse</span> |
| </div> |
| <div class="theme-option" data-theme="terminal"> |
| <div class="theme-preview" style="border-color: #00cc00; background: #0a0a0a;"></div> |
| <span class="theme-name">Terminal</span> |
| </div> |
| </div> |
| <input type="hidden" id="setting-theme-color" value="forest"> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="settings-actions"> |
| <button class="settings-save-btn" id="saveSettingsBtn">SAVE</button> |
| <button class="settings-cancel-btn" id="cancelSettingsBtn">CANCEL</button> |
| </div> |
|
|
| <div class="settings-status" id="settingsStatus"></div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="debug-panel" id="debugPanel"> |
| <div class="debug-header"> |
| <h3>DEBUG: Message History</h3> |
| <button class="debug-close" id="debugClose">×</button> |
| </div> |
| <div class="debug-body"> |
| <pre class="debug-content" id="debugContent">No message history available yet.</pre> |
| </div> |
| </div> |
|
|
| |
| <div class="files-panel" id="filesPanel"> |
| <div class="files-panel-header"> |
| <h3>FILES</h3> |
| <div class="files-panel-controls"> |
| <label class="files-show-hidden"> |
| <input type="checkbox" id="showHiddenFiles"> |
| <span>Hidden</span> |
| </label> |
| <button class="files-upload-btn" id="filesUpload" title="Upload file">+</button> |
| <button class="files-refresh-btn" id="filesRefresh" title="Refresh">↻</button> |
| </div> |
| <button class="files-panel-close" id="filesPanelClose">×</button> |
| </div> |
| <div class="files-panel-body" id="fileTree"> |
| <div class="files-loading">Loading...</div> |
| </div> |
| <div class="files-panel-legend"> |
| <span>Click: insert path</span> |
| <span>Double-click: expand</span> |
| <span>Drag: to input</span> |
| </div> |
| </div> |
|
|
| |
| <div class="sessions-panel" id="sessionsPanel"> |
| <div class="sessions-panel-header"> |
| <h3>SESSIONS</h3> |
| <button class="sessions-panel-close" id="sessionsPanelClose">×</button> |
| </div> |
| <div class="sessions-panel-body"> |
| <div class="sessions-current"> |
| <label>Current session:</label> |
| <div class="sessions-current-name"> |
| <input type="text" id="currentSessionRename" placeholder="Session name" /> |
| <button id="renameSessionBtn" title="Rename">✓</button> |
| </div> |
| </div> |
|
|
| <div class="sessions-divider"></div> |
|
|
| <div class="sessions-new"> |
| <label>New session:</label> |
| <div class="sessions-new-input"> |
| <div class="session-input-wrapper"> |
| <input type="text" id="panelNewSessionName" placeholder="Name..." /> |
| <button type="button" class="session-regenerate-btn" id="panelRegenerateNameBtn" title="Generate new name">↻</button> |
| </div> |
| <button id="panelCreateSessionBtn">CREATE</button> |
| </div> |
| </div> |
|
|
| <div class="sessions-divider"></div> |
|
|
| <div class="sessions-list-section"> |
| <label>Switch to:</label> |
| <div class="sessions-list" id="sessionsList"> |
| <div class="sessions-loading">Loading...</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="settings-dialog-overlay" id="provider-dialog"> |
| <div class="settings-dialog"> |
| <div class="settings-dialog-header"> |
| <h3 id="provider-dialog-title">Add Provider</h3> |
| <button class="settings-dialog-close" onclick="hideProviderDialog()">×</button> |
| </div> |
| <div class="settings-dialog-body"> |
| <div class="dialog-field"> |
| <label class="dialog-label">NAME</label> |
| <input type="text" id="provider-name" class="settings-input" placeholder="e.g., OpenAI, Local vLLM"> |
| </div> |
| <div class="dialog-field"> |
| <label class="dialog-label">ENDPOINT</label> |
| <input type="text" id="provider-endpoint" class="settings-input" placeholder="e.g., https://api.openai.com/v1"> |
| </div> |
| <div class="dialog-field"> |
| <label class="dialog-label">API TOKEN</label> |
| <input type="password" id="provider-token" class="settings-input" placeholder="sk-..."> |
| </div> |
| </div> |
| <div class="settings-dialog-actions"> |
| <button class="settings-save-btn" onclick="saveProviderFromDialog()">SAVE</button> |
| <button class="settings-cancel-btn" onclick="hideProviderDialog()">CANCEL</button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="settings-dialog-overlay" id="model-dialog"> |
| <div class="settings-dialog"> |
| <div class="settings-dialog-header"> |
| <h3 id="model-dialog-title">Add Model</h3> |
| <button class="settings-dialog-close" onclick="hideModelDialog()">×</button> |
| </div> |
| <div class="settings-dialog-body"> |
| <div class="dialog-field"> |
| <label class="dialog-label">DISPLAY NAME</label> |
| <input type="text" id="model-name" class="settings-input" placeholder="e.g., GPT-4o, Claude 3.5"> |
| </div> |
| <div class="dialog-field"> |
| <label class="dialog-label">PROVIDER</label> |
| <select id="model-provider" class="settings-select"> |
| <option value="">-- Select Provider --</option> |
| </select> |
| </div> |
| <div class="dialog-field"> |
| <label class="dialog-label">MODEL ID</label> |
| <input type="text" id="model-model-id" class="settings-input" placeholder="e.g., gpt-4o, claude-3-5-sonnet-20241022"> |
| <span class="dialog-hint">The exact model identifier used in API calls</span> |
| </div> |
| <div class="dialog-field"> |
| <label class="dialog-label">EXTRA PARAMETERS</label> |
| <textarea id="model-extra-params" class="settings-textarea" placeholder='{"enable_thinking": false}' rows="3"></textarea> |
| <span class="dialog-hint">Optional JSON object with extra parameters for API calls (e.g., enable_thinking, temperature)</span> |
| </div> |
| <div class="dialog-field"> |
| <label class="dialog-checkbox-label"><input type="checkbox" id="model-multimodal"> Supports vision / image input</label> |
| </div> |
| </div> |
| <div class="settings-dialog-actions"> |
| <button class="settings-save-btn" onclick="saveModelFromDialog()">SAVE</button> |
| <button class="settings-cancel-btn" onclick="hideModelDialog()">CANCEL</button> |
| </div> |
| </div> |
| </div> |
|
|
| <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js"></script> |
| <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> |
| <script src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script> |
| |
| <div id="usernameOverlay" class="username-overlay" style="display:none"> |
| <div class="username-dialog"> |
| <h2>Welcome to AgentUI</h2> |
| <p>Enter your name to get started</p> |
| <input type="search" id="usernameInput" name="display_nickname" placeholder="Your name" maxlength="30" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-1p-ignore data-lpignore="true" data-bwignore data-form-type="other" role="presentation"> |
| <div id="usernameWarning" class="username-warning" style="display:none"></div> |
| <button id="usernameSubmit">Start</button> |
| <p class="username-notice"><strong>Important:</strong> This is a shared space — other users may access your data. Do not add API keys. Session data is stored for persistence in a private bucket. For private use, <a href="https://github.com/huggingface/agent-ui" target="_blank">clone the repo</a> and run locally.</p> |
| </div> |
| </div> |
|
|
| <script src="utils.js?v=1"></script> |
| <script src="research-ui.js?v=23"></script> |
| <script src="timeline.js?v=1"></script> |
| <script src="sessions.js?v=1"></script> |
| <script src="streaming.js?v=1"></script> |
| <script src="tabs.js?v=1"></script> |
| <script src="workspace.js?v=1"></script> |
| <script src="settings.js?v=1"></script> |
| <script src="app.js?v=1"></script> |
| </body> |
| </html> |
|
|