Spaces:
Running
Running
Reorganize sidebar controls: separate timeline and chat collapse settings
Browse files- "Timeline view: compact" checkbox below legend (collapses agents + hides
turns in timeline only)
- "Chat collapse: agents / tools" checkboxes (collapse action-widgets and
tool-cells in chat only)
- Newly created widgets respect current collapse state
- Checkboxes reset on conversation clear
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- frontend/index.html +12 -4
- frontend/script.js +56 -20
- frontend/style.css +9 -2
frontend/index.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
| 7 |
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet">
|
| 8 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css">
|
| 9 |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
|
| 10 |
-
<link rel="stylesheet" href="style.css?v=
|
| 11 |
</head>
|
| 12 |
<body>
|
| 13 |
<div class="app-container">
|
|
@@ -47,8 +47,13 @@
|
|
| 47 |
<span><span class="legend-box"></span> agent/tool</span>
|
| 48 |
</div>
|
| 49 |
<div class="sidebar-controls">
|
| 50 |
-
<
|
| 51 |
-
<label class="sidebar-checkbox"><input type="checkbox" id="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
</div>
|
| 53 |
<div class="sidebar-resize-handle" id="sidebarResizeHandle"></div>
|
| 54 |
</div>
|
|
@@ -476,6 +481,9 @@
|
|
| 476 |
<textarea id="model-extra-params" class="settings-textarea" placeholder='{"enable_thinking": false}' rows="3"></textarea>
|
| 477 |
<span class="dialog-hint">Optional JSON object with extra parameters for API calls (e.g., enable_thinking, temperature)</span>
|
| 478 |
</div>
|
|
|
|
|
|
|
|
|
|
| 479 |
</div>
|
| 480 |
<div class="settings-dialog-actions">
|
| 481 |
<button class="settings-save-btn" onclick="saveModelFromDialog()">SAVE</button>
|
|
@@ -500,6 +508,6 @@
|
|
| 500 |
</div>
|
| 501 |
|
| 502 |
<script src="research-ui.js?v=23"></script>
|
| 503 |
-
<script src="script.js?v=
|
| 504 |
</body>
|
| 505 |
</html>
|
|
|
|
| 7 |
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet">
|
| 8 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css">
|
| 9 |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
|
| 10 |
+
<link rel="stylesheet" href="style.css?v=103">
|
| 11 |
</head>
|
| 12 |
<body>
|
| 13 |
<div class="app-container">
|
|
|
|
| 47 |
<span><span class="legend-box"></span> agent/tool</span>
|
| 48 |
</div>
|
| 49 |
<div class="sidebar-controls">
|
| 50 |
+
<span class="sidebar-controls-label">Timeline view:</span>
|
| 51 |
+
<label class="sidebar-checkbox"><input type="checkbox" id="compactViewCheckbox"> compact</label>
|
| 52 |
+
</div>
|
| 53 |
+
<div class="sidebar-controls">
|
| 54 |
+
<span class="sidebar-controls-label">Chat collapse:</span>
|
| 55 |
+
<label class="sidebar-checkbox"><input type="checkbox" id="collapseAgentsCheckbox"> agents</label>
|
| 56 |
+
<label class="sidebar-checkbox"><input type="checkbox" id="collapseToolsCheckbox"> tools</label>
|
| 57 |
</div>
|
| 58 |
<div class="sidebar-resize-handle" id="sidebarResizeHandle"></div>
|
| 59 |
</div>
|
|
|
|
| 481 |
<textarea id="model-extra-params" class="settings-textarea" placeholder='{"enable_thinking": false}' rows="3"></textarea>
|
| 482 |
<span class="dialog-hint">Optional JSON object with extra parameters for API calls (e.g., enable_thinking, temperature)</span>
|
| 483 |
</div>
|
| 484 |
+
<div class="dialog-field">
|
| 485 |
+
<label class="dialog-checkbox-label"><input type="checkbox" id="model-multimodal"> Supports vision / image input</label>
|
| 486 |
+
</div>
|
| 487 |
</div>
|
| 488 |
<div class="settings-dialog-actions">
|
| 489 |
<button class="settings-save-btn" onclick="saveModelFromDialog()">SAVE</button>
|
|
|
|
| 508 |
</div>
|
| 509 |
|
| 510 |
<script src="research-ui.js?v=23"></script>
|
| 511 |
+
<script src="script.js?v=90"></script>
|
| 512 |
</body>
|
| 513 |
</html>
|
frontend/script.js
CHANGED
|
@@ -138,6 +138,14 @@ function resetLocalState() {
|
|
| 138 |
showAllTurns = true;
|
| 139 |
agentCounters = getDefaultCounters();
|
| 140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
// Reset timeline data
|
| 142 |
Object.keys(timelineData).forEach(k => delete timelineData[k]);
|
| 143 |
timelineData[0] = { type: 'command', title: 'Task Center', events: [], parentTabId: null, isGenerating: false };
|
|
@@ -821,40 +829,61 @@ function initializeEventListeners() {
|
|
| 821 |
}
|
| 822 |
|
| 823 |
// Sidebar checkboxes
|
| 824 |
-
const
|
| 825 |
-
const
|
| 826 |
-
|
| 827 |
-
|
| 828 |
-
|
| 829 |
-
|
| 830 |
-
|
| 831 |
-
|
| 832 |
-
|
|
|
|
| 833 |
Object.entries(timelineData).forEach(([id, data]) => {
|
| 834 |
if (data.parentTabId !== null) {
|
| 835 |
collapsedAgents.add(String(id));
|
| 836 |
}
|
| 837 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
| 838 |
}
|
| 839 |
renderTimeline();
|
| 840 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 841 |
document.querySelectorAll('.action-widget').forEach(w => {
|
| 842 |
const toggle = w.querySelector('.widget-collapse-toggle');
|
| 843 |
-
if (
|
| 844 |
-
w.classList.remove('collapsed');
|
| 845 |
-
if (toggle) toggle.classList.remove('collapsed');
|
| 846 |
-
} else {
|
| 847 |
w.classList.add('collapsed');
|
| 848 |
if (toggle) toggle.classList.add('collapsed');
|
|
|
|
|
|
|
|
|
|
| 849 |
}
|
| 850 |
});
|
| 851 |
});
|
| 852 |
}
|
| 853 |
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
| 857 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 858 |
});
|
| 859 |
}
|
| 860 |
|
|
@@ -2329,10 +2358,13 @@ async function streamChatResponse(messages, chatContainer, agentType, tabId) {
|
|
| 2329 |
// Create tool-cell box (similar to code-cell)
|
| 2330 |
const toolCell = document.createElement('div');
|
| 2331 |
toolCell.className = 'tool-cell';
|
|
|
|
|
|
|
|
|
|
| 2332 |
toolCell.setAttribute('data-tool-name', data.tool);
|
| 2333 |
const descHtml = description ? `<span class="tool-cell-desc">${escapeHtml(description)}</span>` : '';
|
| 2334 |
toolCell.innerHTML = `
|
| 2335 |
-
<div class="tool-cell-label"><div class="widget-collapse-toggle"></div><span>${label}</span>${descHtml}${createSpinnerHtml()}</div>
|
| 2336 |
<div class="tool-cell-input">${escapeHtml(description)}</div>
|
| 2337 |
`;
|
| 2338 |
toolCell.querySelector('.tool-cell-label').addEventListener('click', () => {
|
|
@@ -2785,15 +2817,19 @@ function updateLastCodeCell(chatContainer, output, isError, images) {
|
|
| 2785 |
function showActionWidget(chatContainer, action, message, targetTabId, taskId = null) {
|
| 2786 |
const widget = document.createElement('div');
|
| 2787 |
widget.className = 'action-widget';
|
|
|
|
|
|
|
|
|
|
| 2788 |
widget.dataset.targetTabId = targetTabId;
|
| 2789 |
|
| 2790 |
// Display task_id as title if provided
|
| 2791 |
const titleDisplay = taskId ? taskId : action.toUpperCase();
|
|
|
|
| 2792 |
|
| 2793 |
widget.innerHTML = `
|
| 2794 |
<div class="action-widget-clickable">
|
| 2795 |
<div class="action-widget-header">
|
| 2796 |
-
<div class="widget-collapse-toggle"></div>
|
| 2797 |
<span class="action-widget-type">${action.toUpperCase()}: ${escapeHtml(titleDisplay)}</span>
|
| 2798 |
<div class="action-widget-bar-right">
|
| 2799 |
<div class="orbit-indicator">
|
|
|
|
| 138 |
showAllTurns = true;
|
| 139 |
agentCounters = getDefaultCounters();
|
| 140 |
|
| 141 |
+
// Reset sidebar checkboxes
|
| 142 |
+
const compactCb = document.getElementById('compactViewCheckbox');
|
| 143 |
+
if (compactCb) compactCb.checked = false;
|
| 144 |
+
const collapseAgentsCb = document.getElementById('collapseAgentsCheckbox');
|
| 145 |
+
if (collapseAgentsCb) collapseAgentsCb.checked = false;
|
| 146 |
+
const collapseToolsCb = document.getElementById('collapseToolsCheckbox');
|
| 147 |
+
if (collapseToolsCb) collapseToolsCb.checked = false;
|
| 148 |
+
|
| 149 |
// Reset timeline data
|
| 150 |
Object.keys(timelineData).forEach(k => delete timelineData[k]);
|
| 151 |
timelineData[0] = { type: 'command', title: 'Task Center', events: [], parentTabId: null, isGenerating: false };
|
|
|
|
| 829 |
}
|
| 830 |
|
| 831 |
// Sidebar checkboxes
|
| 832 |
+
const compactViewCheckbox = document.getElementById('compactViewCheckbox');
|
| 833 |
+
const collapseAgentsCheckbox = document.getElementById('collapseAgentsCheckbox');
|
| 834 |
+
const collapseToolsCheckbox = document.getElementById('collapseToolsCheckbox');
|
| 835 |
+
|
| 836 |
+
// Compact view: affects timeline only (collapse agents + hide turns)
|
| 837 |
+
if (compactViewCheckbox) {
|
| 838 |
+
compactViewCheckbox.addEventListener('change', () => {
|
| 839 |
+
const compact = compactViewCheckbox.checked;
|
| 840 |
+
if (compact) {
|
| 841 |
+
// Collapse all agent boxes in timeline
|
| 842 |
Object.entries(timelineData).forEach(([id, data]) => {
|
| 843 |
if (data.parentTabId !== null) {
|
| 844 |
collapsedAgents.add(String(id));
|
| 845 |
}
|
| 846 |
});
|
| 847 |
+
showAllTurns = false;
|
| 848 |
+
} else {
|
| 849 |
+
collapsedAgents.clear();
|
| 850 |
+
showAllTurns = true;
|
| 851 |
}
|
| 852 |
renderTimeline();
|
| 853 |
+
});
|
| 854 |
+
}
|
| 855 |
+
|
| 856 |
+
// Chat collapse: agents — affects action-widgets in chat only
|
| 857 |
+
if (collapseAgentsCheckbox) {
|
| 858 |
+
collapseAgentsCheckbox.addEventListener('change', () => {
|
| 859 |
+
const collapse = collapseAgentsCheckbox.checked;
|
| 860 |
document.querySelectorAll('.action-widget').forEach(w => {
|
| 861 |
const toggle = w.querySelector('.widget-collapse-toggle');
|
| 862 |
+
if (collapse) {
|
|
|
|
|
|
|
|
|
|
| 863 |
w.classList.add('collapsed');
|
| 864 |
if (toggle) toggle.classList.add('collapsed');
|
| 865 |
+
} else {
|
| 866 |
+
w.classList.remove('collapsed');
|
| 867 |
+
if (toggle) toggle.classList.remove('collapsed');
|
| 868 |
}
|
| 869 |
});
|
| 870 |
});
|
| 871 |
}
|
| 872 |
|
| 873 |
+
// Chat collapse: tools — affects tool-cells in chat only
|
| 874 |
+
if (collapseToolsCheckbox) {
|
| 875 |
+
collapseToolsCheckbox.addEventListener('change', () => {
|
| 876 |
+
const collapse = collapseToolsCheckbox.checked;
|
| 877 |
+
document.querySelectorAll('.tool-cell').forEach(w => {
|
| 878 |
+
const toggle = w.querySelector('.widget-collapse-toggle');
|
| 879 |
+
if (collapse) {
|
| 880 |
+
w.classList.add('collapsed');
|
| 881 |
+
if (toggle) toggle.classList.add('collapsed');
|
| 882 |
+
} else {
|
| 883 |
+
w.classList.remove('collapsed');
|
| 884 |
+
if (toggle) toggle.classList.remove('collapsed');
|
| 885 |
+
}
|
| 886 |
+
});
|
| 887 |
});
|
| 888 |
}
|
| 889 |
|
|
|
|
| 2358 |
// Create tool-cell box (similar to code-cell)
|
| 2359 |
const toolCell = document.createElement('div');
|
| 2360 |
toolCell.className = 'tool-cell';
|
| 2361 |
+
if (document.getElementById('collapseToolsCheckbox')?.checked) {
|
| 2362 |
+
toolCell.classList.add('collapsed');
|
| 2363 |
+
}
|
| 2364 |
toolCell.setAttribute('data-tool-name', data.tool);
|
| 2365 |
const descHtml = description ? `<span class="tool-cell-desc">${escapeHtml(description)}</span>` : '';
|
| 2366 |
toolCell.innerHTML = `
|
| 2367 |
+
<div class="tool-cell-label"><div class="widget-collapse-toggle${document.getElementById('collapseToolsCheckbox')?.checked ? ' collapsed' : ''}"></div><span>${label}</span>${descHtml}${createSpinnerHtml()}</div>
|
| 2368 |
<div class="tool-cell-input">${escapeHtml(description)}</div>
|
| 2369 |
`;
|
| 2370 |
toolCell.querySelector('.tool-cell-label').addEventListener('click', () => {
|
|
|
|
| 2817 |
function showActionWidget(chatContainer, action, message, targetTabId, taskId = null) {
|
| 2818 |
const widget = document.createElement('div');
|
| 2819 |
widget.className = 'action-widget';
|
| 2820 |
+
if (document.getElementById('collapseAgentsCheckbox')?.checked) {
|
| 2821 |
+
widget.classList.add('collapsed');
|
| 2822 |
+
}
|
| 2823 |
widget.dataset.targetTabId = targetTabId;
|
| 2824 |
|
| 2825 |
// Display task_id as title if provided
|
| 2826 |
const titleDisplay = taskId ? taskId : action.toUpperCase();
|
| 2827 |
+
const agentCollapsed = document.getElementById('collapseAgentsCheckbox')?.checked;
|
| 2828 |
|
| 2829 |
widget.innerHTML = `
|
| 2830 |
<div class="action-widget-clickable">
|
| 2831 |
<div class="action-widget-header">
|
| 2832 |
+
<div class="widget-collapse-toggle${agentCollapsed ? ' collapsed' : ''}"></div>
|
| 2833 |
<span class="action-widget-type">${action.toUpperCase()}: ${escapeHtml(titleDisplay)}</span>
|
| 2834 |
<div class="action-widget-bar-right">
|
| 2835 |
<div class="orbit-indicator">
|
frontend/style.css
CHANGED
|
@@ -364,10 +364,17 @@ body {
|
|
| 364 |
|
| 365 |
/* Sidebar Controls */
|
| 366 |
.sidebar-controls {
|
| 367 |
-
padding:
|
| 368 |
border-top: 1px solid var(--border-primary);
|
| 369 |
display: flex;
|
| 370 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
}
|
| 372 |
|
| 373 |
.sidebar-checkbox {
|
|
|
|
| 364 |
|
| 365 |
/* Sidebar Controls */
|
| 366 |
.sidebar-controls {
|
| 367 |
+
padding: 6px 12px;
|
| 368 |
border-top: 1px solid var(--border-primary);
|
| 369 |
display: flex;
|
| 370 |
+
align-items: center;
|
| 371 |
+
gap: 8px;
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
.sidebar-controls-label {
|
| 375 |
+
font-size: 9px;
|
| 376 |
+
color: var(--text-muted);
|
| 377 |
+
white-space: nowrap;
|
| 378 |
}
|
| 379 |
|
| 380 |
.sidebar-checkbox {
|